zy7_oldserver
1
fd601de
% 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)