Spaces:
Runtime error
Runtime error
| % script to evaluate a network for generating synthetic CT images from XCAT | |
| % phantom data | |
| genDir = 'A:/MIDL/Dominik_MIDL/genCT'; % directory containing network directories with generated CT data | |
| genList = dir(genDir); % list all files in directory | |
| genNames = {genList(3:end).name}; % list all the filnames | |
| nrNetworks = numel(genNames); % number of networks | |
| %% | |
| %read in XCAT data | |
| XCATDataDir = 'A:/MIDL/Dominik_MIDL/XCAT'; % directory of XCAT data used for CT generation | |
| XCATListDir = dir(XCATDataDir); % list all files in selected directory | |
| XCATDirNames = {XCATListDir(3:end).name}; % list all the filnames | |
| nrXCATPhantoms = numel(XCATDirNames); % number of phantoms in directory | |
| %% | |
| % initialize parameters to evaluate | |
| NoiseEvaluation = 0; % are the noise properties to be evaluated? | |
| ReferenceNPSEvaluation = 0; % patient NPS to be evaluated? | |
| EdgeEvaluation = 1; % are the edge and feature properties to be evaluated? | |
| NiftiFromDicom = 1; % were the reference segmentation masks extracted from nii files converted from dicom files? Put 0 for .nrrd | |
| DicomCTImages = 1; % were the reference patient images dicom files? Put 0 for .nrrd | |
| %% | |
| if EdgeEvaluation | |
| [Result.FSIM,Result.SSIM,Result.MAE,Result.FaultyPixel,Result.EPR,Result.EdgeGenRatio,Result.GMSdev] = deal(cell(nrXCATPhantoms,1)); %,Result.MAD,Result.NMSE | |
| [Data.PCBP,Data.MAE,Data.SSIM,Data.FSIM,Data.GMSD,Data.EGR] = deal(cell(nrXCATPhantoms,nrNetworks)); % container for statistics of all metrics | |
| end | |
| %% | |
| if NoiseEvaluation | |
| %% | |
| % initiale cells for metrics | |
| [Result.NPSAccuracy,Result.NPSCorrelation,Result.NoiseMagnitude,Result.MaxRatio] = deal(cell(nrXCATPhantoms,1)); | |
| [Data.NM,Data.PCC,Data.MPE,Data.MMR] = deal(cell(nrXCATPhantoms,nrNetworks)); | |
| %% | |
| % read segmentations of generated data | |
| genSegmDir = 'A:/Dominik_MIDL/genSegm'; % directories containing generated CT data | |
| %% | |
| if ReferenceNPSEvaluation | |
| % read in training and segmentation data to calculate real noise properties for comparison | |
| segmDir = 'A:/Dominik_MIDL/Patsegm'; % directories containing segmentation of real patient data | |
| segmList = dir(segmDir); | |
| segmNames = {segmList(3:end).name}; | |
| %% | |
| % read patient data | |
| % patDir = 'D:\Russ\CT_Images\synCT\Patient'; % directories containing real patient data | |
| patDir = 'A:/Dominik_MIDL/Patnrrd'; % directories containing real patient data | |
| patList = dir(patDir); | |
| patNames = {patList(3:end).name}; | |
| [Data.ReferenceNPS2D,Data.ReferenceFreq,Data.ReferenceNPScurves,Data.LiverValues] = deal(cell(numel(segmNames),1)); | |
| %% | |
| % segment patient data and calculate NPS | |
| for i = 1:numel(segmNames) | |
| patScanDir = [patDir '\' patNames{i}]; | |
| patScanList = dir(patScanDir); | |
| patScanNames = {patScanList(3:end).name}; | |
| if DicomCTImages | |
| % sortn is third party code | |
| patScanNames = sortn(patScanNames); % sort the cell array in natural order, if they are dicom images | |
| end | |
| [patData,patPixelSpacing] = Read_Dicom_File(patScanDir,patScanNames); | |
| segmData = double(niftiread([segmDir '\' segmNames{i}])); | |
| if NiftiFromDicom | |
| segmData = Nifti_Coordinate_Trafo1(segmData); % transform the coordinate system for correct representation, depends, whether the image to be segmented was created from a nrrd file (2) or dicom file (1) | |
| else | |
| segmData = Nifti_Coordinate_Trafo2(segmData); % transform the coordinate system for correct representation, depends, whether the image to be segmented was created from a nrrd file (2) or dicom file (1) | |
| end | |
| liverData = segmData.*patData; | |
| Data.ReferenceNPS2D{i} = patPixelSpacing(1)*patPixelSpacing(2)*FFT_Segmented_Noise(liverData); | |
| [Data.ReferenceFreq{i},Data.ReferenceNPScurves{i}] = Radial_from_2D_NPS(Data.ReferenceNPS2D{i},patPixelSpacing(1),1); | |
| % calculate reference STD | |
| liverData(segmData==0) = NaN; | |
| Data.LiverSTD{i} = nanstd(liverData(:)); | |
| end | |
| %% | |
| % compute convex hull of radial NPS in order to create a valid | |
| % variable space for generated NPS | |
| refNPS = vertcat(Data.ReferenceNPScurves{:})'; | |
| Data.ReferenceNPS = mean(refNPS,2)'; | |
| Data.minNPS = min(refNPS,[],2); | |
| Data.maxNPS = max(refNPS,[],2); | |
| Data.LiverNoiseMean = mean(cell2mat(Data.LiverSTD(:))); | |
| Data.LiverNoiseSTD = std(cell2mat(Data.LiverSTD(:))); | |
| end | |
| end | |
| clear refNPS genList XCATListDir XCATListDir segmList i liverData patData patDir patList patNames patPixelSpacing patScanDir patScanList patScanNames segmData segmDir segmNames | |
| %% | |
| for k = 1:nrNetworks | |
| %% | |
| % read in XCAT stuff for prepping | |
| [XCATData,XCATPixelSpacing,XCATSliceThickness] = Read_Dicom_File(XCATDataDir,XCATDirNames(1)); % read in first file to extract pixel spacing and slice thickness | |
| [nrXCATRows,nrXCATColumns,nrXCATSlices] = size(XCATData); % extract size of generated image matrix | |
| %% | |
| % read in generated image stuff | |
| network = genNames{k}; | |
| genDataDir = [genDir '\' network]; | |
| genListDir = dir(genDataDir); % list all files in selected directory | |
| genDirNames = {genListDir(3:end).name}; % list all the filnames | |
| nrGenPhantoms = numel(genDirNames); % number of phantoms in directory | |
| genData = Read_Dicom_File(genDataDir,genDirNames(1)); % read in first file to extract pixel spacing and slice thickness | |
| [nrGenRows,nrGenColumns,nrGenSlices] = size(genData); % extract size of generated image matrix | |
| %% | |
| % compare generated and XCAT data size and return error if not matching | |
| if nrXCATRows ~= nrGenRows || nrXCATColumns ~= nrGenColumns | |
| error('Size of XCAT data and generated data not matching') | |
| elseif nrXCATPhantoms ~= nrGenPhantoms | |
| error('Number of Phantoms in XCAT and generated data not matching') | |
| end | |
| n = nrXCATSlices - nrGenSlices; % parameter depending on how many slices were used for training the networks | |
| clear nrGenPhantoms nrXCATSlices XCATData nrGenRows nrGenColumns genData genListDir nrXCATRows nrXCATColumns | |
| %% | |
| for i = 1:nrXCATPhantoms | |
| %% | |
| phantom = genDirNames{i}; | |
| genData = Read_Dicom_File(genDataDir,{phantom}); % read in generated data | |
| XCATData = Read_Dicom_File(XCATDataDir,XCATDirNames(i)); % read in XCAT data | |
| XCATData = XCATData(:,:,1+n/2:end-n/2); % first and last n/2 slices are not in synthetic CTs | |
| %% | |
| if EdgeEvaluation | |
| XCATContour = XCATData ~= -1000; % extract XCAT body contour, always 0 outside the body | |
| compXCATContour = imcomplement(XCATContour); % inverts the logical binary mask | |
| segmData = XCATContour.*genData; | |
| segmData(XCATContour==0) = -1000; | |
| negData = compXCATContour.*genData; | |
| negData(compXCATContour==0) = -2000; | |
| absXCAT = XCATData; % create new XCAT data with -2000 outside of the body contour for better excluding it while absolute comparison | |
| absXCAT(XCATContour==0) = -2000; | |
| absSegmData = segmData; % create new segmented data with -2000 outside of the body contour for better excluding it while absolute comparison | |
| absSegmData(XCATContour==0) = -2000; | |
| [FSIMtmp,SSIMtmp,MAEtmp,FaultyPixeltmp,EPRtmp,EdgeGenRatiotmp,GMSdevtmp] = deal(zeros(nrGenSlices,1)); %,MADtmp,NMSEtmp | |
| for j = 1:nrGenSlices | |
| % read in single axial slices | |
| gentmp = segmData(:,:,j); | |
| absGentmp = absSegmData(:,:,j); | |
| XCATtmp = XCATData(:,:,j); | |
| absXCATtmp = absXCAT(:,:,j); | |
| negDatatmp = negData(:,:,j); | |
| % evaluate the slices | |
| FSIMtmp(j) = FeatureSIM(rescale(XCATtmp,0,255),rescale(gentmp,0,255)); % calculates the feature similarity index | |
| SSIMtmp(j) = ssim(rescale(gentmp),rescale(XCATtmp)); % calculates the structural similarity index | |
| MAEtmp(j) = Mean_Absolute_Error(absXCATtmp,absGentmp); % calculates the mean absolute error | |
| % NMSEtmp(j) = Normalized_Mean_Square_Error(absXCATtmp,absGentmp); % calculates the normalized mean square error | |
| FaultyPixeltmp(j) = Faulty_Pixel(negDatatmp); % calculates the number of 'faulty pixels in the generated image | |
| [EPRtmp(j),EdgeGenRatiotmp(j)] = Edge_Preservation_Ratio(XCATtmp,gentmp); % calculates the edge preservation ratio and | |
| GMSdevtmp(j) = Gradient_Magnitude_Similarity_Deviation(XCATtmp,gentmp); % calculates the gradient magnitude similarity deviation | |
| % tmp = MAD_index(XCATtmp,gentmp); % calculates the most apparent distortion index | |
| % MADtmp(j) = tmp.MAD; | |
| end | |
| Result.FSIM{i} = FSIMtmp; | |
| Data.FSIM{i,k} = FSIMtmp; | |
| Result.SSIM{i} = SSIMtmp; | |
| Data.SSIM{i,k} = SSIMtmp; | |
| Result.MAE{i} = MAEtmp; | |
| Data.MAE{i,k} = MAEtmp; | |
| % Result.NMSE{i} = NMSEtmp; | |
| Result.FaultyPixel{i} = FaultyPixeltmp; | |
| Data.PCBP{i,k} = FaultyPixeltmp; | |
| Result.EPR{i} = EPRtmp; | |
| Result.EdgeGenRatio{i} = EdgeGenRatiotmp; | |
| Data.EGR{i,k} = EdgeGenRatiotmp; | |
| Result.GMSdev{i} = GMSdevtmp; | |
| Data.GMSD{i,k} = GMSdevtmp; | |
| % Result.MAD{i} = MADtmp; | |
| clear absXCATtmp absGentmp absSegmData absXCAT tmp i j genData XCATData XCATContour compXCATContour segmData negData gentmp XCATtmp negDatatmp FSIMtmp SSIMtmp Sharpnesstmp MAEtmp NMSEtmp FaultyPixeltmp EPRtmp EdgeGenRatiotmp GMSdevtmp MADtmp | |
| end | |
| %% | |
| if NoiseEvaluation | |
| %% | |
| % get deep learning segmentation | |
| phanName = phantom(1:end-5); | |
| segmDir = [genSegmDir '\' network]; | |
| segmList = dir(segmDir); | |
| segmList = {segmList(3:end).name}; | |
| liverMask = 1; | |
| if ~isempty(segmList) | |
| for m = 1:numel(segmList) | |
| genSegmFile = segmList{m}; | |
| if contains(genSegmFile,phanName) % checks if the phantom name is contained in the selected segmentation | |
| liverMask = double(niftiread([segmDir '\' genSegmFile])); | |
| liverMask = Nifti_Coordinate_Trafo2(liverMask); | |
| end | |
| end | |
| end | |
| if liverMask | |
| % read in binary masks for liver tissue tissue | |
| % liverValue = 51.26; | |
| % liverMask = round(XCATData,2) == liverValue; % round due to more precision in actual values than in imshow plot | |
| liverValue1 = 51.72; | |
| liverValue2 = 52.39; | |
| liverValue3 = 53.42; | |
| liverMask = round(XCATData,2) == liverValue1; | |
| if numel(nonzeros(liverMask)) == 0 | |
| liverMask = round(XCATData,2) == liverValue2; | |
| end | |
| if numel(nonzeros(liverMask)) == 0 | |
| liverMask = round(XCATData,2) == liverValue3; | |
| end | |
| end | |
| %% | |
| % apply masks to CT Image | |
| liverData = liverMask.*genData; % segment Data using the Liver Mask | |
| %% | |
| % calculate 2D NPS | |
| normFactor = XCATPixelSpacing(1)*XCATPixelSpacing(2); % normalization factor depending on XCAT/gen Pixel spacing | |
| Data.NPS2D{i} = normFactor*FFT_Segmented_Noise(liverData); | |
| %% | |
| % calculate radial NPS, calculate the percentage of inliers and | |
| % NPS accuracy | |
| [Data.Frequency{i},Data.NPS{i}] = Radial_from_2D_NPS(Data.NPS2D{i},XCATPixelSpacing(1),1); | |
| Result.NPSAccuracy{i} = Generated_NPS_Accuracy(Data.NPS{i},Data.ReferenceNPS); | |
| Data.MPE{i,k} = Generated_NPS_Accuracy(Data.NPS{i},Data.ReferenceNPS); | |
| %% | |
| % normalize to 1 and calculate pearson correlation | |
| tmp = corrcoef(Data.NPS{i}/max(Data.NPS{i}(:)),Data.ReferenceNPS/max(Data.ReferenceNPS(:))); % Pearson correlation of normalized NPS | |
| Result.NPSCorrelation{i} = tmp(1,2); | |
| Data.PCC{i,k} = tmp(1,2); | |
| %% | |
| % calculate generated noise standard deviation and max ratio | |
| liverData(liverMask==0) = NaN; | |
| Result.NoiseMagnitude{i} = nanstd(liverData(:)); | |
| Data.NM{i,k} = nanstd(liverData(:)); | |
| Result.MaxRatio{i} = max(Data.NPS2D{i}(:))/max(Data.NPS{i}(:)); | |
| Data.MMR{i,k} = max(Data.NPS2D{i}(:))/max(Data.NPS{i}(:)); | |
| end | |
| end | |
| %% | |
| % write the results in a csv | |
| % write results in csv | |
| Metrics = cell2table(fieldnames(Result),'VariableNames',{'Metrics'}); | |
| data = struct2cell(Result); % writes the result data in a cell | |
| data = horzcat(data{:}); % unfolds the result cells in a new cell | |
| dataOut = cell2table(Cell_End_Results(data),'VariableNames',{network(1:end-10)}); | |
| % dataOut = Cell_End_Results([Result.FSIM,Result.SSIM,Result.MAE,Result.FaultyPixel,Result.EPR,Result.DecVariable,Result.GMSdev]); %,Result.MAD,Result.NMSE]); | |
| if k == 1 | |
| resultData = [Metrics,dataOut]; | |
| if NoiseEvaluation | |
| [NPS2DData,NPSData] = deal(cell(nrXCATPhantoms,nrNetworks)); | |
| NPS2DData(:,1) = Data.NPS2D; | |
| NPSData(:,1) = Data.NPS; | |
| end | |
| else | |
| resultData = [resultData,dataOut]; | |
| if NoiseEvaluation | |
| NPS2DData(:,k) = Data.NPS2D; | |
| NPSData(:,k) = Data.NPS; | |
| end | |
| end | |
| end | |
| %% | |
| % choose save directory | |
| saveFile = 'A:\Dominik_MIDL\Results\'; | |
| writetable(resultData,saveFile) |