matRad_calcQualityIndicators

Purpose ^

matRad QI calculation

Synopsis ^

function qi = matRad_calcQualityIndicators(cst,pln,doseCube,refGy,refVol)

Description ^

 matRad QI calculation
 
 call
   qi = matRad_calcQualityIndicators(cst,pln,doseCube)
   qi = matRad_calcQualityIndicators(cst,pln,doseCube,refGy,refVol)

 input
   cst:                matRad cst struct
   pln:                matRad pln struct
   doseCube:           arbitrary doseCube (e.g. physicalDose)
   refGy: (optional)   array of dose values used for V_XGy calculation
                       default is [40 50 60]
   refVol:(optional)   array of volumes (0-100) used for D_X calculation
                       default is [2 5 95 98]
                       NOTE: Call either both or none!

 output
   qi                  various quality indicators like CI, HI (for 
                       targets) and DX, VX within a structure set   

 References
   van't Riet et. al., IJROBP, 1997 Feb 1;37(3):731-6.
   Kataria et. al., J Med Phys. 2012 Oct-Dec; 37(4)

 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 Copyright 2016 the matRad development team. 
 
 This file is part of the matRad project. It is subject to the license 
 terms in the LICENSE file found in the top-level directory of this 
 distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part 
 of the matRad project, including this file, may be copied, modified, 
 propagated, or distributed except according to the terms contained in the 
 LICENSE file.

 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Cross-reference information ^

This function calls: This function is called by:

Source code ^

0001 function qi = matRad_calcQualityIndicators(cst,pln,doseCube,refGy,refVol)
0002 % matRad QI calculation
0003 %
0004 % call
0005 %   qi = matRad_calcQualityIndicators(cst,pln,doseCube)
0006 %   qi = matRad_calcQualityIndicators(cst,pln,doseCube,refGy,refVol)
0007 %
0008 % input
0009 %   cst:                matRad cst struct
0010 %   pln:                matRad pln struct
0011 %   doseCube:           arbitrary doseCube (e.g. physicalDose)
0012 %   refGy: (optional)   array of dose values used for V_XGy calculation
0013 %                       default is [40 50 60]
0014 %   refVol:(optional)   array of volumes (0-100) used for D_X calculation
0015 %                       default is [2 5 95 98]
0016 %                       NOTE: Call either both or none!
0017 %
0018 % output
0019 %   qi                  various quality indicators like CI, HI (for
0020 %                       targets) and DX, VX within a structure set
0021 %
0022 % References
0023 %   van't Riet et. al., IJROBP, 1997 Feb 1;37(3):731-6.
0024 %   Kataria et. al., J Med Phys. 2012 Oct-Dec; 37(4)
0025 %
0026 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0027 %
0028 % Copyright 2016 the matRad development team.
0029 %
0030 % This file is part of the matRad project. It is subject to the license
0031 % terms in the LICENSE file found in the top-level directory of this
0032 % distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part
0033 % of the matRad project, including this file, may be copied, modified,
0034 % propagated, or distributed except according to the terms contained in the
0035 % LICENSE file.
0036 %
0037 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0038 
0039 
0040 matRad_cfg = MatRad_Config.instance();
0041 
0042 if ~exist('refVol', 'var') || isempty(refVol)
0043     refVol = [2 5 50 95 98];
0044 end
0045 
0046 if ~exist('refGy', 'var') || isempty(refGy)
0047     refGy = floor(linspace(0,max(doseCube(:)),6)*10)/10;
0048 end
0049 
0050     
0051 % calculate QIs per VOI
0052 qi = struct;
0053 for runVoi = 1:size(cst,1)
0054     
0055     indices     = cst{runVoi,4}{1};
0056     numOfVoxels = numel(indices); 
0057     voiPrint = sprintf('%3d %20s',cst{runVoi,1},cst{runVoi,2}); %String that will print quality indicators
0058     
0059     % get Dose, dose is sorted to simplify calculations
0060     doseInVoi    = sort(doseCube(indices));
0061         
0062     if ~isempty(doseInVoi)
0063         
0064         qi(runVoi).name = cst{runVoi,2};
0065         
0066         % easy stats
0067         qi(runVoi).mean = mean(doseInVoi);
0068         qi(runVoi).std  = std(doseInVoi);
0069         qi(runVoi).max  = doseInVoi(end);
0070         qi(runVoi).min  = doseInVoi(1);
0071 
0072         voiPrint = sprintf('%s - Mean dose = %5.2f Gy +/- %5.2f Gy (Max dose = %5.2f Gy, Min dose = %5.2f Gy)\n%27s', ...
0073                            voiPrint,qi(runVoi).mean,qi(runVoi).std,qi(runVoi).max,qi(runVoi).min,' ');
0074 
0075         DX = @(x) matRad_interp1(linspace(0,1,numOfVoxels),doseInVoi,(100-x)*0.01);
0076         VX = @(x) numel(doseInVoi(doseInVoi >= x)) / numOfVoxels;
0077 
0078         % create VX and DX struct fieldnames at runtime and fill
0079         for runDX = 1:numel(refVol)
0080             qi(runVoi).(strcat('D_',num2str(refVol(runDX)))) = DX(refVol(runDX));
0081             voiPrint = sprintf('%sD%d%% = %5.2f Gy, ',voiPrint,refVol(runDX),DX(refVol(runDX)));
0082         end
0083         voiPrint = sprintf('%s\n%27s',voiPrint,' ');
0084         for runVX = 1:numel(refGy)
0085             sRefGy = num2str(refGy(runVX),3);
0086             qi(runVoi).(['V_' strrep(sRefGy,'.','_') 'Gy']) = VX(refGy(runVX));
0087             voiPrint = sprintf(['%sV' sRefGy 'Gy = %6.2f%%, '],voiPrint,VX(refGy(runVX))*100);
0088         end
0089         voiPrint = sprintf('%s\n%27s',voiPrint,' ');
0090 
0091         % if current voi is a target -> calculate homogeneity and conformity
0092         if strcmp(cst{runVoi,3},'TARGET') > 0      
0093 
0094             % loop over target objectives and get the lowest dose objective
0095             referenceDose = inf;
0096             
0097             if isstruct(cst{runVoi,6})
0098                 cst{runVoi,6} = num2cell(arrayfun(@matRad_DoseOptimizationFunction.convertOldOptimizationStruct,cst{runVoi,6}));
0099             end
0100             
0101             for runObjective = 1:numel(cst{runVoi,6})
0102                % check if this is an objective that penalizes underdosing
0103                obj = cst{runVoi,6}{runObjective};
0104                if ~isa(obj,'matRad_DoseOptimizationFunction')
0105                    try
0106                        obj = matRad_DoseOptimizationFunction.createInstanceFromStruct(obj);
0107                    catch ME
0108                        matRad_cfg.dispWarning('Objective/Constraint not valid!\n%s',ME.message)
0109                        continue;
0110                    end
0111                end
0112                
0113                %if strcmp(cst{runVoi,6}(runObjective).type,'square deviation') > 0 || strcmp(cst{runVoi,6}(runObjective).type,'square underdosing') > 0
0114                if isa(obj,'DoseObjectives.matRad_SquaredDeviation') || isa(obj,'DoseObjectives.matRad_SquaredUnderdosing')
0115                    referenceDose = (min(obj.getDoseParameters(),referenceDose))/pln.numOfFractions;
0116                end            
0117             end
0118 
0119             if referenceDose == inf 
0120                 voiPrint = sprintf('%s%s',voiPrint,'Warning: target has no objective that penalizes underdosage, ');
0121             else
0122  
0123                 StringReferenceDose = regexprep(num2str(round(referenceDose*100)/100),'\D','_');
0124                 % Conformity Index, fieldname contains reference dose
0125                 VTarget95 = sum(doseInVoi >= 0.95*referenceDose); % number of target voxels recieving dose >= 0.95 dPres
0126                 VTreated95 = sum(doseCube(:) >= 0.95*referenceDose);  %number of all voxels recieving dose >= 0.95 dPres ("treated volume")
0127                 qi(runVoi).(['CI_' StringReferenceDose 'Gy']) = VTarget95^2/(numOfVoxels * VTreated95); 
0128 
0129                 % Homogeneity Index (one out of many), fieldname contains reference dose
0130                 qi(runVoi).(['HI_' StringReferenceDose 'Gy']) = (DX(5) - DX(95))/referenceDose * 100;
0131 
0132                 voiPrint = sprintf('%sCI = %6.4f, HI = %5.2f for reference dose of %3.1f Gy\n',voiPrint,...
0133                                    qi(runVoi).(['CI_' StringReferenceDose 'Gy']),qi(runVoi).(['HI_' StringReferenceDose 'Gy']),referenceDose);
0134             end
0135         end
0136         %We do it this way so the percentages in the string are not interpreted as format specifiers
0137         matRad_cfg.dispInfo('%s\n',voiPrint);    
0138     else        
0139         matRad_cfg.dispInfo('%d %s - No dose information.',cst{runVoi,1},cst{runVoi,2});        
0140     end
0141 end
0142 
0143 % assign VOI names which could be corrupted due to empty structures
0144 listOfFields = fieldnames(qi);
0145 for i = 1:size(cst,1)
0146   indices     = cst{i,4}{1};
0147   doseInVoi    = sort(doseCube(indices));
0148   if isempty(doseInVoi)
0149       for j = 1:numel(listOfFields)
0150           qi(i).(listOfFields{j}) = NaN;
0151       end
0152       qi(i).name = cst{i,2};
0153   end
0154 end
0155 
0156 end
0157

| Generated by m2html © 2005