Code covered by the BSD License  

Highlights from
Siemens DICOM sort and convert to NIfTI

image thumbnail
from Siemens DICOM sort and convert to NIfTI by Simon Robinson
Converts Siemens MRI DICOM data into NIfTI format, and/or anonymises and sorts into scan directories

reformat_data_func(data)
function data = reformat_data_func(data)

%   if the 'Advanced' feature are selected in dicom_sort_convert_main, this
%   function reformats a dataset with 3 or 4 dimensions into one with up to
%   7.  The dimensions of these are specified by the dims parameters, and
%   are, in order
%   [x][y][z][time][echos][channels][phase/mag]
%   The first 3 dimensions are always image x,y,z. After that, dimensions
%   are only used if variation in that dimension is present (more than one
%   time point, echo, channel, p/m)


% NON-MOSIAC
% odims(1) = x
% odims(2) = y
% odims(3) = time-echo-z-p/m-channels (changes least frequently -> changes most frequently)

% MOSIAC
% odims(1) = x
% odims(2) = y
% odims(3) = z
% odims(4) = ???time-echo-p/m-channels (changes least frequently -> changes most frequently)???

% dims(1) = x
% dims(2) = y
% dims(3) = z
% dims(4) = time
% dims(5) = echos
% dims(6) = channels
% dims(7) = phase/magnitude

dims(1:7) = 1;
odims = 0;
reformat = 'no';
datalabel = '[x,y,z';

convert_format = data.convert_format;
current_dir = data.current_dir;
current_nfiles = data.current_nfiles;
n_channels = data.current_header_pars.n_channels;

if data.current_analyze_struct.hdr.dime.dim(1) == 4
    odims (1:4) = data.current_analyze_struct.hdr.dime.dim(2:5);
else
    odims (1:3) = data.current_analyze_struct.hdr.dime.dim(2:4);
end

z = data.current_header_pars.dim_nslices;

dims (1) = odims(1);
dims (2) = odims(2);
dims (3) = z;

%   next dimension time (for EPI-type) or diffusion gradient
dims(4) = data.current_header_pars.dim_nr;
if data.current_header_pars.dim_nr > 1
    switch data.current_header_pars.sequence_type
        case 'ep2d_diff'
            if data.current_header_pars.dim_ngd > 1
                dims(dim) = data.current_header_pars.dim_ngd;
                datalabel = [datalabel ',diff_g'];
                %DTI with multiple repetitions
                if (data.current_header_pars.dim_nr > 1)
                    disp('!!! lRepetitions gives NR > 1 - assuming this is number of diffusion directions');
                    dims(dim) = data.current_header_pars.dim_nr;
                    data.warning_present = 'yes';
                    this_warning_text = 'lRepetitions gives NR > 1 - assuming this is number of diffusion directions - check reformatted data';
                    data.warning_text = sprintf('%sScan: %s. %s\n', data.warning_text, data.current_scan, this_warning_text);
                end
            end
        otherwise
            %   for time-series data
            datalabel = [datalabel ',t'];
    end
end
%   next dimension is echo number
if (data.current_header_pars.nechos > 1)
    reformat = 'yes';
    dims(5) = data.current_header_pars.nechos;
    datalabel = [datalabel ',echo'];
end
%   next dimension is channel
if strcmp(data.current_header_pars.sep_channels, 'yes')
    if z > 1 % only reformat if more than one slice
        reformat = 'yes';
    end
    dims(6) = n_channels;
    datalabel = [datalabel ',channel'];
end
%   next dimension is phase/magnitude
if strcmp(data.current_header_pars.data_type, 'MP')
    dim = dim + 1;
    reformat = 'yes';
    dims(7) = 2;
    datalabel = [datalabel ',phase/mag'];
end
datalabel = [datalabel ']'];

if (strcmp(data.current_mosaic_flag, 'mosaic') ~= 1 && (dims(4) > 1)) %only reformat NR>1 data if not MOSAIC
    reformat = 'yes';
end

%   below, some scans that shouldn't be reformatted
if numel(findstr(data.current_dcminfo.ImageType, 'T2 MAP'))==1 ||  numel(findstr(data.current_dcminfo.ImageType, 'T2_STAR MAP'))==1
    reformat = 'no';
end

if strcmp(reformat,'yes')
    disp([' - scan ' data.current_scan ' is ' datalabel ', reformatting into those dimensions']);
    current_reform_dir = fullfile(current_dir,'reform');
    s = warning ('query', 'MATLAB:MKDIR:DirectoryExists') ;	    % get current state
    warning ('off', 'MATLAB:MKDIR:DirectoryExists') ;
    mkdir(current_reform_dir);
    warning (s) ;						    % restore state
    switch convert_format
        case 'nifti'
            extension = '.nii';
        case 'analyze'
            extension = '';
    end
    readfile = fullfile(current_dir, sprintf('Image%s', extension));
    %   check that the product of the reformatted dimensions equals the old dimensions, and the number of files
    if prod(odims(3:end)) ~= current_nfiles
        disp(sprintf('!!! The scan dimensions are %i, which means there should be %i files, but there are %i', num2str(odims), prod(odims(3:end)), current_nfiles));
        data.warning_present = 'yes';
        this_warning_text = sprintf('!!! There should be %i files in this series, but there are %i',prod(odims(3:end)), current_nfiles);
        data.warning_text = sprintf('%sScan: %s. %s\n', data.warning_text, data.current_scan, this_warning_text);
        return;
    end
    if prod(odims(3:end)) ~= prod(dims(3:end))
        dim_ratio = prod(dims(3:end))/prod(odims(3:end));
        if round(dim_ratio) == dim_ratio && round(n_channels/dim_ratio) == n_channels/dim_ratio
            disp(sprintf('!!! The old scan dimensions are %s, and the new dimensions %s, which differ by a factor %f', num2str(odims), num2str(dims(1:dim)), dim_ratio));            
            disp(sprintf('!!! Assuming that the real number of channels is %i, not %i, trying to continue, check scan', n_channels/dim_ratio, n_channels));
            data.warning_present = 'yes';
            this_warning_text = sprintf('!!! Changed number of coil channels from %i to %i to reformat', n_channels, n_channels/dim_ratio);
            data.warning_text = sprintf('%sScan: %s. %s\n', data.warning_text, data.current_scan, this_warning_text);
            n_channels = n_channels/dim_ratio;
            if strcmp(data.current_header_pars.data_type, 'MP')
                dims(dim-1) = n_channels;
            else
                dims(dim) = n_channels;
            end  
        else
            disp(sprintf('!!! The old scan dimensions are %s, and the new dimensions %s, which differ by the a factor %f, and would make the guess of the real number of channel %f', num2str(odims), num2str(dims), dim_ratio, n_channels/dim_ratio));
            data.warning_present = 'yes';
            this_warning_text = sprintf('!!! The number of old and new dimensions doesn''t match (scan incomplete?), not reformatting', n_channels, n_channels/dim_ratio);
            data.warning_text = sprintf('%sScan: %s. %s\n', data.warning_text, data.current_scan, this_warning_text);
            return;
        end
    end
    try
        new_image = zeros(dims(1),dims(2),dims(3),dims(4),dims(5),dims(6),dims(7),data.current_header_pars.precision);
    catch
        disp('!!! Could not create the image for reformatting');
        return;
    end
    try
        old_image_nii = load_nii(readfile);
    catch
        disp('!!! Could not load the old image to perform reformatting');
        data.warning_present = 'yes';
        this_warning_text = '!!! Image couldn''t be loaded prior to reformatting';
        data.warning_text = sprintf('%sScan: %s. %s\n', data.warning_text, data.current_scan, this_warning_text);
        return;
    end
    if (strcmp(data.current_mosaic_flag, 'mosaic') ~= 1)
        try
            %         logical indexing slices
            for j = 1:dims(4) % time
                for k = 1:dims(5) % echos
                    for l = 1:dims(6) % channels
                        for m = 1:dims(7) % phase/magnitude
                            %disp(['putting elements ' num2str((j-1)*dims(5)*dims(3)*dims(7)*dims(6)+(k-1)*dims(3)*dims(7)*dims(6)+((1:1:dims(3))-1)*dims(7)*dims(6)+(m-1)*dims(6)+l) ' into ' num2str(k) ',' num2str(1:1:dims(3)) ',' num2str(j) ',' num2str(m) ',' num2str(l)]);
                            new_image(:,:,1:1:dims(3),j,k,l,m) = old_image_nii.img(:,:,(j-1)*dims(5)*dims(3)*dims(7)*dims(6)+(k-1)*dims(3)*dims(7)*dims(6)+((1:1:dims(3))-1)*dims(7)*dims(6)+(m-1)*dims(6)+l);
                        end
                    end
                end
            end
            data.warning_present = 'yes';
            this_warning_text = ['was reformatted to ' datalabel ' in /reformat)' ];
            data.warning_text = sprintf('%sScan: %s. %s\n', data.warning_text, data.current_scan, this_warning_text);
            if strcmp(data.current_header_pars.sep_channels,'yes') && (data.current_header_pars.dim_nr > 1)
                disp('  -  swapping slice order');
                %%
                if iseven(z)
                    slice_acq_order=[2:2:z 1:2:z-1];
                else
                    slice_acq_order=[1:2:z 2:2:z];
                end
                [dummy, new_slice_order] = sort(slice_acq_order);
                new_image=new_image(:,:,new_slice_order,:,:,:);
                %%
            end
        catch
            disp(['!!!' data.current_scan ': Couldn''t reformat data into new matrix - in reformat_data_func.m']);
            data.warning_present = 'yes';
            this_warning_text = ['Warning!!!: couldn''t be reformatted to ' datalabel];
            data.warning_text = sprintf('%sScan: %s. %s\n', data.warning_text, data.current_scan, this_warning_text);
        end
    else
        disp(['Scan ' data.current_scan ': reformatting not yet programmed for MOSAIC format']);
    end
    old_image_hdr = load_nii_hdr(readfile);
    %   sort out VC mode for the 24-channel coil
    if (dims(6) == 23) || (dims(6) == 25) || (dims(6) == 50) %23 = VC with 2 broken channels turned off - clutching at straws here
        current_reform_dir_vc = fullfile(current_reform_dir,'vc');
        s = warning ('query', 'MATLAB:MKDIR:DirectoryExists') ;	    % get current state
        warning ('off', 'MATLAB:MKDIR:DirectoryExists') ;
        mkdir(current_reform_dir_vc);
        current_reform_dir = fullfile(current_reform_dir,'other');
        s = warning ('query', 'MATLAB:MKDIR:DirectoryExists') ;	    % get current state
        warning ('off', 'MATLAB:MKDIR:DirectoryExists') ;
        mkdir(current_reform_dir);
        warning (s) ;						    % restore state
        new_image_vc = squeeze(new_image(:,:,:,:,:,1));
        new_image_vc_nii = make_nii_sr(new_image_vc, 4);
        new_image_vc_nii.hdr = centre_header(new_image_vc_nii.hdr);
        new_image_vc_nii.hdr.dime.pixdim(2:4) = old_image_hdr.dime.pixdim(2:4);
        save_nii(new_image_vc_nii, fullfile(current_reform_dir_vc, ['Image' extension]));
        new_image = new_image(:,:,:,:,:,2:end);
    end
    new_image = squeeze(new_image);
    new_image_nii = make_nii_sr(new_image, 4);
    new_image_nii.hdr = centre_header(new_image_nii.hdr);
    new_image_nii.hdr.dime.pixdim(2:4) = old_image_hdr.dime.pixdim(2:4);
    save_nii(new_image_nii, fullfile(current_reform_dir, ['Image' extension]));
end

Contact us at files@mathworks.com