function ct = matRad_importDicomCt(ctList, resolution, dicomMetaBool, grid, visBool)
0001 function ct = matRad_importDicomCt(ctList, resolution, dicomMetaBool, grid, visBool)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 matRad_cfg = MatRad_Config.instance();
0041
0042 matRad_cfg.dispInfo('\nimporting ct-cube...');
0043
0044
0045 if ~exist('visBool','var')
0046 visBool = 0;
0047 end
0048
0049
0050 numOfSlices = size(ctList,1);
0051 matRad_cfg.dispInfo('\ncreating info...')
0052
0053 sliceThicknessStandard = true;
0054 for i = 1:numOfSlices
0055
0056 if verLessThan('matlab','9')
0057 tmpDicomInfo = dicominfo(ctList{i,1});
0058 else
0059 tmpDicomInfo = dicominfo(ctList{i,1},'UseDictionaryVR',true);
0060 end
0061
0062
0063
0064 ctInfo(i).PixelSpacing = tmpDicomInfo.PixelSpacing;
0065 ctInfo(i).ImagePositionPatient = tmpDicomInfo.ImagePositionPatient;
0066 ctInfo(i).SliceThickness = tmpDicomInfo.SliceThickness;
0067 ctInfo(i).ImageOrientationPatient = tmpDicomInfo.ImageOrientationPatient;
0068 ctInfo(i).PatientPosition = tmpDicomInfo.PatientPosition;
0069 ctInfo(i).Rows = tmpDicomInfo.Rows;
0070 ctInfo(i).Columns = tmpDicomInfo.Columns;
0071 ctInfo(i).Width = tmpDicomInfo.Width;
0072 ctInfo(i).Height = tmpDicomInfo.Height;
0073 ctInfo(i).RescaleSlope = tmpDicomInfo.RescaleSlope;
0074 ctInfo(i).RescaleIntercept = tmpDicomInfo.RescaleIntercept;
0075
0076
0077
0078 if isempty(ctInfo(i).SliceThickness)
0079
0080 if sliceThicknessStandard
0081 matRad_cfg.dispWarning('Non-standard use of SliceThickness Attribute (empty), trying to overwrite with SpacingBetweenSlices');
0082 sliceThicknessStandard = false;
0083 end
0084 ctInfo(i).SliceThickness = tmpDicomInfo.SpacingBetweenSlices;
0085 end
0086
0087 if i == 1
0088 completeDicom = tmpDicomInfo;
0089 end
0090
0091 matRad_progress(i,numOfSlices);
0092 end
0093
0094
0095
0096 CoordList = [ctInfo.ImagePositionPatient]';
0097 [~, indexing] = sort(CoordList(:,3));
0098
0099 ctList = ctList(indexing);
0100 ctInfo = ctInfo(indexing);
0101
0102
0103 if size(unique([ctInfo.PixelSpacing]','rows'),1) > 1
0104 matRad_cfg.dispError('Different pixel size in different CT slices');
0105 end
0106
0107 coordsOfFirstPixel = [ctInfo.ImagePositionPatient];
0108 if numel(unique(coordsOfFirstPixel(1,:))) > 1 || numel(unique(coordsOfFirstPixel(2,:))) > 1
0109 matRad_cfg.dispError('Ct slices are not aligned');
0110 end
0111 if sum(diff(coordsOfFirstPixel(3,:))<=0) > 0
0112 matRad_cfg.dispError('Ct slices not monotonically increasing');
0113 end
0114 if numel(unique([ctInfo.Rows])) > 1 || numel(unique([ctInfo.Columns])) > 1
0115 matRad_cfg.dispError('Ct slice sizes inconsistent');
0116 end
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 if isempty(regexp(ctInfo(1).PatientPosition,{'S','P'}, 'once'))
0134 matRad_cfg.dispError(['This Patient Position is not supported by matRad.'...
0135 ' As of now only ''HFS'' (Head First-Supine), ''FFS'''...
0136 ' (Feet First-Supine), '...
0137 '''HFP'' (Head First-Prone), and ''FFP'''...
0138 ' (Feet First-Prone) can be processed.'])
0139 end
0140
0141
0142 matRad_cfg.dispInfo('reading slices...')
0143 origCt = zeros(ctInfo(1).Height, ctInfo(1).Width, numOfSlices);
0144 for i = 1:numOfSlices
0145 currentFilename = ctList{i};
0146 [currentImage, map] = dicomread(currentFilename);
0147 origCt(:,:,i) = currentImage(:,:);
0148
0149
0150 if visBool
0151 if ~isempty(map)
0152 image(ind2rgb(uint8(63*currentImage/max(currentImage(:))),map));
0153 xlabel('x [voxelnumber]')
0154 ylabel('y [voxelnumber]')
0155 title(['Slice # ' int2str(i) ' of ' int2str(numOfSlices)])
0156 else
0157 image(ind2rgb(uint8(63*currentImage/max(currentImage(:))),bone));
0158 xlabel('x [voxelnumber]')
0159 ylabel('y [voxelnumber]')
0160 title(['Slice # ' int2str(i) ' of ' int2str(numOfSlices)])
0161 end
0162 axis equal tight;
0163 pause(0.1);
0164 end
0165 matRad_progress(i,numOfSlices);
0166 end
0167
0168
0169
0170
0171
0172 matRad_cfg.dispInfo('\nz-coordinates taken from ImagePositionPatient\n')
0173
0174
0175
0176 xDir = ctInfo(1).ImageOrientationPatient(1:3);
0177 yDir = ctInfo(1).ImageOrientationPatient(4:6);
0178 nonStandardDirection = false;
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 if nonStandardDirection
0203 matRad_cfg.dispInfo(['Non-standard patient orientation.\n'...
0204 'CT might not fit to contoured structures\n'])
0205 end
0206
0207
0208 matRad_cfg.dispInfo('\nInterpolating CT cube...');
0209 if exist('grid','var')
0210 ct = matRad_interpDicomCtCube(origCt, ctInfo, resolution, grid);
0211 else
0212 ct = matRad_interpDicomCtCube(origCt, ctInfo, resolution);
0213 end
0214 matRad_cfg.dispInfo('finished!\n');
0215
0216
0217 ct.dicomInfo.PixelSpacing = ctInfo(1).PixelSpacing;
0218 tmp = [ctInfo.ImagePositionPatient];
0219 ct.dicomInfo.SlicePositions = tmp(3,:);
0220 ct.dicomInfo.SliceThickness = [ctInfo.SliceThickness];
0221 ct.dicomInfo.ImagePositionPatient = ctInfo(1).ImagePositionPatient;
0222 ct.dicomInfo.ImageOrientationPatient = ctInfo(1).ImageOrientationPatient;
0223 ct.dicomInfo.PatientPosition = ctInfo(1).PatientPosition;
0224 ct.dicomInfo.Width = ctInfo(1).Width;
0225 ct.dicomInfo.Height = ctInfo(1).Height;
0226 ct.dicomInfo.RescaleSlope = ctInfo(1).RescaleSlope;
0227 ct.dicomInfo.RescaleIntercept = ctInfo(1).RescaleIntercept;
0228 if isfield(completeDicom, 'Manufacturer')
0229 ct.dicomInfo.Manufacturer = completeDicom.Manufacturer;
0230 end
0231 if isfield(completeDicom, 'ManufacturerModelName')
0232 ct.dicomInfo.ManufacturerModelName = completeDicom.ManufacturerModelName;
0233 end
0234 if isfield(completeDicom, 'ConvolutionKernel')
0235 ct.dicomInfo.ConvolutionKernel = completeDicom.ConvolutionKernel;
0236 end
0237
0238
0239 if isfield(completeDicom,'PatientName') && dicomMetaBool == true
0240 ct.dicomInfo.PatientName = completeDicom.PatientName;
0241 end
0242 if dicomMetaBool == true
0243 ct.dicomMeta = completeDicom;
0244 end
0245
0246 ct.timeStamp = datestr(clock);
0247
0248
0249 matRad_cfg.dispInfo('\nconversion of ct-Cube to Hounsfield units...');
0250 ct = matRad_calcHU(ct);
0251 matRad_cfg.dispInfo('finished!\n');
0252
0253 end