Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of LET modifying objectives #706

Open
wants to merge 49 commits into
base: dev_varRBErobOpt
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
a2f3241
Dirty dose calculation and objectives
lisaseckler Nov 21, 2023
a3b1f91
LET Objectives
lisaseckler Dec 13, 2023
4d2c215
Merge branch 'dev_varRBErobOpt' of https://github.com/e0404/matRad in…
lisaseckler Dec 13, 2023
56b4ac4
Test change
lisaseckler Dec 20, 2023
249054b
LETd Objective
lisaseckler Dec 21, 2023
6a202f8
Objective Variance Implementation
lisaseckler Jan 11, 2024
90c3be3
LET experiments for PTCOG
lisaseckler Jan 22, 2024
593443a
Cleaning branch
lisaseckler Jan 26, 2024
b2ea438
Function Test
lisaseckler Feb 1, 2024
7e8fee4
Test DD
lisaseckler Feb 2, 2024
b3a3e12
test change
lisaseckler Feb 2, 2024
cf03bab
Delete matRad_Beam2DirtyDose.asv
lisaseckler Mar 1, 2024
0a15bfc
Delete matRad_DoseComparison.asv
lisaseckler Mar 1, 2024
4a7fec9
Delete optimization/+DoseObjectives/matRad_LETDirtyDose.asv
lisaseckler Mar 1, 2024
fab2177
Delete optimization/@matRad_OptimizationProblem/matRad_objectiveFunct…
lisaseckler Mar 1, 2024
1359231
Delete optimization/@matRad_OptimizationProblem/matRad_objectiveGradi…
lisaseckler Mar 1, 2024
c09e74f
Delete optimization/projections/matRad_DirtyDoseProjection.asv
lisaseckler Mar 1, 2024
57d5495
Delete optimization/projections/matRad_LETdProjection.asv
lisaseckler Mar 1, 2024
f5b4266
Update matRad_Beam2DirtyDose.m
lisaseckler Mar 1, 2024
c11d27a
Delete matRad_Beam2DirtyDoseMCN_WED.m
lisaseckler Mar 1, 2024
18f2aff
Delete matRad_Beam2mLETDoseMCN.m
lisaseckler Mar 1, 2024
d7537b4
Update matRad_Beam2DirtyDose.m
lisaseckler Mar 1, 2024
e5c083a
Delete matRad_UnderdosingTesting.asv
lisaseckler Mar 1, 2024
d01e7c0
Update and rename matRad_UnderdosingTesting.m to matRad_DirtyDoseUnde…
lisaseckler Mar 1, 2024
6047145
Delete matRad_calcLETmask.asv
lisaseckler Mar 1, 2024
5f71dc0
Delete matRad_fluenceOptimization.asv
lisaseckler Mar 1, 2024
c15485f
Cleaning LET Optimization
lisaseckler Mar 1, 2024
fe7a317
Merge branch 'dev_varRBErobOpt' of https://github.com/lisaseckler/mat…
lisaseckler Mar 1, 2024
c5cb8b4
Clean up
lisaseckler Mar 27, 2024
143ac52
Testing examples and deleting scripts
lisaseckler Mar 27, 2024
621e7db
renaming file
lisaseckler Mar 27, 2024
a97197d
changing variable names
lisaseckler Mar 27, 2024
0516c2e
Merge branch 'e0404:dev_varRBErobOpt' into dev_varRBErobOpt
lisaseckler Mar 27, 2024
627c2b6
Merge branch 'dev_varRBErobOpt' of https://github.com/lisaseckler/mat…
lisaseckler Mar 27, 2024
3a88bec
deleting comments
lisaseckler Mar 27, 2024
c489f32
deleting dicom
lisaseckler Mar 27, 2024
a6d4eba
delete
lisaseckler Mar 27, 2024
44eedec
delete
lisaseckler Mar 27, 2024
f120062
delete
lisaseckler Mar 27, 2024
54516f1
delete
lisaseckler Mar 27, 2024
c9c77dd
delete
lisaseckler Mar 27, 2024
d6e1040
name
lisaseckler Mar 27, 2024
969aebc
Examples
lisaseckler Apr 22, 2024
c3b26c1
Description of LETmask
lisaseckler May 3, 2024
3a3efe9
Merge branch 'dev' into pr/706
wahln Jun 28, 2024
2d05c9b
some streamlining of the calculation of dirty dose and the LET masks
wahln Jun 28, 2024
57eea22
Merge branch 'dev_varRBErobOpt' into pr/706
wahln Jun 28, 2024
1b9251b
remove the tempfile
wahln Jun 28, 2024
32a31c3
Merge branch 'dev_varRBErobOpt' into pr/706
wahln Jun 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ List of all matRad developers that contributed code (alphabetical)
* Giuseppe Pezzano
* Daniel Ramirez
* Carsten Scholz
* Lisa Seckler
* Camilo Sevilla
* Alexander Stadler
* Uwe Titt
Expand Down
238 changes: 238 additions & 0 deletions examples/matRad_example15_DirtyDose.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
%% Welcome to a dirty dose testing script
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% What is the script about?
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% the script will tell you how you can use the dirty dose objectives and
% how the dose distribution will look like if you do that
% follow the steps and you will succeed :)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% open matRad files and delete everything in the workspace
matRad_rc

%% load an easy phantom like the TG119.mat
load("TG119.mat")

%% Plan and Geometry
% choose your modality... but seriously choose protons!!
pln.radiationMode = 'protons'; % either photons / protons / helium / carbon
pln.machine = 'Generic';
pln.numOfFractions = 30;


% beam geometry settings
pln.propStf.bixelWidth = 5; % [mm] / also corresponds to lateral spot spacing for particles
pln.propStf.gantryAngles = [45 0 -45];
pln.propStf.couchAngles = zeros(numel(pln.propStf.gantryAngles),1);
pln.propStf.numOfBeams = numel(pln.propStf.gantryAngles);
pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(cst,ct,0);
% optimization settings
pln.propDoseCalc.calcLET = 1; % very important, don't forget that one!

pln.propOpt.runDAO = false; % 1/true: run DAO, 0/false: don't / will be ignored for particles
pln.propOpt.runSequencing = false; % 1/true: run sequencing, 0/false: don't / will be ignored for particles and also triggered by runDAO below
pln.propOpt.spatioTemp = 0;

% dose calculation settings
pln.propDoseCalc.doseGrid.resolution.x = 3; % [mm]
pln.propDoseCalc.doseGrid.resolution.y = 3; % [mm]
pln.propDoseCalc.doseGrid.resolution.z = 3; % [mm]
% pln(1).propDoseCalc.doseGrid.resolution = ct.resolution;
quantityOpt = 'RBExD'; % options: physicalDose, effect, RBExD
%=======================================> Model check error in bioModel
modelName = 'constRBE'; % none: for photons, protons, carbon % constRBE: constant RBE for photons and protons
% MCN: McNamara-variable RBE model for protons % WED: Wedenberg-variable RBE model for protons
% LEM: Local Effect Model for carbon ions


scenGenType = 'nomScen'; % scenario creation type 'nomScen' 'wcScen' 'impScen' 'rndScen'

% retrieve bio model parameters
pln.bioParam = matRad_bioModel(pln.radiationMode,quantityOpt, modelName);

% retrieve scenarios for dose calculation and optimziation
pln.multScen = matRad_multScen(ct,scenGenType);
stf = matRad_generateStf(ct,cst,pln);

%% Dose calculation
% Dij Calculation --> only for dose
dij = matRad_calcParticleDose(ct,stf,pln,cst);

% Dirty Dose Calculation --> adding dirty dose. The number describes your
% LET threshold -> that you can change but everything else has to stay like
% this
dij = matRad_calcDirtyDose(2,dij);

%% Optimization
% yeyy only the optimization has to be done
resultGUI = matRad_fluenceOptimization(dij,cst,pln);

% IMPORTANT: If you want to save your results, rename them! Maybe they will
% get overwritten later

%% Plotting
% Let's see how it looks
cube = resultGUI.physicalDose;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
figure
subplot(2,1,1)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('physicalDose')
zoom(4)

cube = resultGUI.dirtyDose;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
subplot(2,1,2)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('dirtyDose without DD objective')
zoom(4)
%% Adding dirty dose
% the cst is important!
% for adding a dirty dose objective choose a structure like the Core

% REMEMBER: Always set dirty dose objectives as a secondary objective and
% have a dose objective as your first objective
% You can change the penalty and the prescribed dirtydose if you like
cst{1,6}{2} = struct(DirtyDoseObjectives.matRad_SquaredOverdosingDirtyDose(300,0));

%% Generate the Geometry again
stf = matRad_generateStf(ct,cst,pln);

%% Dose calculation
% Dij Calculation --> only for dose
dij = matRad_calcParticleDose(ct,stf,pln,cst);

% Dirty Dose Calculation --> adding dirty dose. The number describes your
% LET threshold -> that you can change but everything else has to stay like
% this
dij = matRad_calcDirtyDose(2,dij);

%% Optimization
% yeyy only the optimization has to be done
resultGUI = matRad_fluenceOptimization(dij,cst,pln);

%% Well done your first dirty dose calculation is ready!
% Let's see how it looks
cube = resultGUI.physicalDose;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
figure
subplot(2,1,1)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('physicalDose')
zoom(4)

cube = resultGUI.dirtyDose;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
subplot(2,1,2)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('dirtyDose with DD objective in Core')
zoom(4)

%% Now with the Target
% make sure to delete cst{1,6}{2} = struct(DirtyDoseObjectives.matRad_SquaredOverdosingDirtyDose(300,0));
clear('cst')
load("TG119.mat")
%% Adding dirty dose
% the cst is important!
% for adding a dirty dose objective choose a structure like the OuterTarget

% REMEMBER: Always set dirty dose objectives as a secondary objective and
% have a dose objective as your first objective
% You can change the penalty and the prescribed dirtydose if you like
cst{2,6}{2} = struct(DirtyDoseObjectives.matRad_SquaredUnderdosingDirtyDose(300,4));

%% Generate the Geometry again
stf = matRad_generateStf(ct,cst,pln);

%% Dose calculation
% Dij Calculation --> only for dose
dij = matRad_calcParticleDose(ct,stf,pln,cst);

% Dirty Dose Calculation --> adding dirty dose. The number describes your
% LET threshold -> that you can change but everything else has to stay like
% this
dij = matRad_calcDirtyDose(2,dij);

%% Optimization
% yeyy only the optimization has to be done
resultGUI = matRad_fluenceOptimization(dij,cst,pln);

%% Well done your second dirty dose calculation is ready!
% Let's see how it looks
cube = resultGUI.physicalDose;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
figure
subplot(2,1,1)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('physicalDose')
zoom(4)

cube = resultGUI.dirtyDose;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
subplot(2,1,2)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('dirtyDose with DD objective in Target')
zoom(4)

%% Now with the Core and Target
% make sure to delete cst{2,6}{2} = struct(DirtyDoseObjectives.matRad_SquaredUnderdosingDirtyDose(300,4));
clear('cst')
load("TG119.mat")
%% Adding dirty dose
% the cst is important!
% for adding a dirty dose objective choose two structures like the Core and OuterTarget

% REMEMBER: Always set dirty dose objectives as a secondary objective and
% have a dose objective as your first objective
% You can change the penalty and the prescribed dirtydose if you like
cst{1,6}{2} = struct(DirtyDoseObjectives.matRad_SquaredOverdosingDirtyDose(300,0));
cst{2,6}{2} = struct(DirtyDoseObjectives.matRad_SquaredUnderdosingDirtyDose(300,4));

%% Generate the Geometry again
stf = matRad_generateStf(ct,cst,pln);

%% Dose calculation
% Dij Calculation --> only for dose
dij = matRad_calcParticleDose(ct,stf,pln,cst);

% Dirty Dose Calculation --> adding dirty dose. The number describes your
% LET threshold -> that you can change but everything else has to stay like
% this
dij = matRad_calcDirtyDose(2,dij);

%% Optimization
% yeyy only the optimization has to be done
resultGUI = matRad_fluenceOptimization(dij,cst,pln);

%% Well done your third dirty dose calculation is ready!
% Let's see how it looks
cube = resultGUI.physicalDose;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
figure
subplot(2,1,1)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('physicalDose')
zoom(4)

cube = resultGUI.dirtyDose;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
subplot(2,1,2)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('dirtyDose with DD objective in Core and Target')
zoom(4)
138 changes: 138 additions & 0 deletions examples/matRad_example16_LETd.m
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we merge examples 16,17,18 into one example comparing the different objectives?

Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
%% Welcome to a LETd testing script
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% What is the script about?
%%%%%%%%%%%%%%%%%%%%%%%%%%%
% the script will tell you how you can use the LETd SquaredUnderdosing objective and
% how the dose distribution will look like if you do that
% follow the steps and you will succeed :)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% open matRad files and delete everything in the workspace
matRad_rc

%% load an easy phantom like the TG119.mat
load("TG119.mat")

%% Plan and Geometry
% choose your modality... but seriously choose protons!!
pln.radiationMode = 'protons'; % either photons / protons / helium / carbon
pln.machine = 'Generic';
pln.numOfFractions = 30;


% beam geometry settings
pln.propStf.bixelWidth = 5; % [mm] / also corresponds to lateral spot spacing for particles
pln.propStf.gantryAngles = [45 0 -45];
pln.propStf.couchAngles = zeros(numel(pln.propStf.gantryAngles),1);
pln.propStf.numOfBeams = numel(pln.propStf.gantryAngles);
pln.propStf.isoCenter = ones(pln.propStf.numOfBeams,1) * matRad_getIsoCenter(cst,ct,0);
% optimization settings
pln.propDoseCalc.calcLET = 1; % very important, don't forget that one!

pln.propOpt.runDAO = false; % 1/true: run DAO, 0/false: don't / will be ignored for particles
pln.propOpt.runSequencing = false; % 1/true: run sequencing, 0/false: don't / will be ignored for particles and also triggered by runDAO below
pln.propOpt.spatioTemp = 0;

% dose calculation settings
pln.propDoseCalc.doseGrid.resolution.x = 3; % [mm]
pln.propDoseCalc.doseGrid.resolution.y = 3; % [mm]
pln.propDoseCalc.doseGrid.resolution.z = 3; % [mm]
% pln(1).propDoseCalc.doseGrid.resolution = ct.resolution;
quantityOpt = 'RBExD'; % options: physicalDose, effect, RBExD
%=======================================> Model check error in bioModel
modelName = 'constRBE'; % none: for photons, protons, carbon % constRBE: constant RBE for photons and protons
% MCN: McNamara-variable RBE model for protons % WED: Wedenberg-variable RBE model for protons
% LEM: Local Effect Model for carbon ions


scenGenType = 'nomScen'; % scenario creation type 'nomScen' 'wcScen' 'impScen' 'rndScen'

% retrieve bio model parameters
pln.bioParam = matRad_bioModel(pln.radiationMode,quantityOpt, modelName);

% retrieve scenarios for dose calculation and optimziation
pln.multScen = matRad_multScen(ct,scenGenType);
stf = matRad_generateStf(ct,cst,pln);

%% Dose calculation
% Dij Calculation --> only for dose
dij = matRad_calcParticleDose(ct,stf,pln,cst);

% Dirty Dose Calculation --> adding dirty dose. The number describes your
% LET threshold -> that you can change but everything else has to stay like
% this
dij = matRad_calcDirtyDose(2,dij);

%% Optimization
% yeyy only the optimization has to be done
resultGUI = matRad_fluenceOptimization(dij,cst,pln);

% IMPORTANT: If you want to save your results, rename them! Maybe they will
% get overwritten later

%% Plotting
% Let's see how it looks
cube = resultGUI.physicalDose;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
figure
subplot(2,1,1)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('physicalDose')
zoom(4)

cube = resultGUI.LETd;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
subplot(2,1,2)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('LETd without Ld objective')
zoom(4)
%% Adding LETd
% the cst is important!
% for adding a LETd objective choose a structure like the OuterTarget

% REMEMBER: Always set LETd objectives as a secondary objective and
% have a dose objective as your first objective
% You can change the penalty and the prescribed LETd if you like
cst{2,6}{2} = struct(LETdObjectives.matRad_SquaredUnderdosingLETd(100,0));

%% Generate the Geometry again
stf = matRad_generateStf(ct,cst,pln);

%% Dose calculation
% Dij Calculation --> only for dose
dij = matRad_calcParticleDose(ct,stf,pln,cst);

% Dirty Dose Calculation --> adding dirty dose. The number describes your
% LET threshold -> that you can change but everything else has to stay like
% this
dij = matRad_calcDirtyDose(2,dij);

%% Optimization
% yeyy only the optimization has to be done
resultGUI = matRad_fluenceOptimization(dij,cst,pln);

%% Well done your first LETd calculation is ready!
% Let's see how it looks
cube = resultGUI.physicalDose;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
figure
subplot(2,1,1)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('physicalDose')
zoom(4)

cube = resultGUI.LETd;
plane = 3;
slice = 80;
doseWindow = [min(cube(:)) max(cube(:))];
subplot(2,1,2)
matRad_plotSliceWrapper(gca,ct,cst,1,cube,plane,slice,[],[],colorcube,[],doseWindow,[],[]);
title('LETd with Ld in Target')
zoom(4)

Loading
Loading