Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/JenHardt/matRad into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
JenHardt committed Feb 7, 2023
2 parents 9f4af93 + 27ad9ff commit aab03e9
Show file tree
Hide file tree
Showing 16 changed files with 441 additions and 92 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This is a basic workflow to help you get started with Actions
name: Testing
name: Tests
# Controls when the action will run.
on: [push, pull_request, workflow_dispatch]
jobs:
Expand Down
123 changes: 123 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
cff-version: 1.2.0
message: "If you use matRad, consider citing it and the corresponding research paper"
authors:
- family-names: "Ackermann"
given-names: "Benjamin"
- family-names: "Bangert"
given-names: "Mark"
- family-names: "Bennan"
given-names: "Amit Ben Antony"
- family-names: "Burigo"
given-names: "Lucas"
- family-names: "Cabal"
given-names: "Gonzalo"
- family-names: "Cisternas"
given-names: "Eduardo"
- family-names: "Charton"
given-names: "Louis"
- family-names: "Christiansen"
given-names: "Eric"
- family-names: "Ecker"
given-names: "Swantje"
- family-names: "Ellerbrock"
given-names: "Malte"
- family-names: "Gabryś"
given-names: "Hubert"
- family-names: "Handrack"
given-names: "Josefine"
- family-names: "Heath"
given-names: "Emily"
- family-names: "Hermann"
given-names: "Cindy"
- family-names: "Homolka"
given-names: "Noa"
- family-names: "Jäkel"
given-names: "Oliver"
- family-names: "Klinge"
given-names: "Thomas"
- family-names: "Mairani"
given-names: "Andrea"
- family-names: "Mescher"
given-names: "Hennig"
- family-names: "Müller"
given-names: "Lucas-Raphael"
- family-names: "Neishabouri"
given-names: "Ahmad"
- family-names: "Palkowitsch"
given-names: "Martina"
- family-names: "Parodi"
given-names: "Katia"
- family-names: "Pezzano"
given-names: "Giuseppe"
- family-names: "Ramirez"
given-names: "Daniel"
- family-names: "Stadler"
given-names: "Alexander"
- family-names: "Ulrich"
given-names: "Silke"
- family-names: "Wahl"
given-names: "Niklas"
orcid: "https://orcid.org/0000-0002-1451-223X"
- family-names: "Welsch"
given-names: "Jona"
- family-names: "Wieser"
given-names: "Hans-Peter"
- family-names: "Winter"
given-names: "Johanna"
- family-names: "Xu"
given-names: "Tong"

title: "matRad"
version: 2.10.1
doi: 10.5281/zenodo.3879616
date-released: 2020-06-05
url: "http://www.matRad.org"
location: "Heidelberg"
organization: "Deutsches Krebsforschungszentrum"
preferred-citation:
type: article
authors:
- family-names: "Wieser"
given-names: "Hans-Peter"
- family-names: "Cisternas"
given-names: "Eduardo"
- family-names: "Wahl"
given-names: "Niklas"
orcid: "https://orcid.org/0000-0002-1451-223X"
- family-names: "Ulrich"
given-names: "Silke"
- family-names: "Stadler"
given-names: "Alexander"
- family-names: "Mescher"
given-names: "Hennig"
- family-names: "Müller"
given-names: "Lucas-Raphael"
- family-names: "Klinge"
given-names: "Thomas"
- family-names: "Gabryś"
given-names: "Hubert"
- family-names: "Burigo"
given-names: "Lucas"
- family-names: "Mairani"
given-names: "Andrea"
- family-names: "Ecker"
given-names: "Swantje"
- family-names: "Ackermann"
given-names: "Benjamin"
- family-names: "Ellerbrock"
given-names: "Malte"
- family-names: "Parodi"
given-names: "Katia"
- family-names: "Jäkel"
given-names: "Oliver"
- family-names: "Bangert"
given-names: "Mark"

doi: 10.1002/mp.12251
journal: "Medical Physics"
start: 2556
end: 2568
title: "Development of the open-source dose calculation and optimization toolkit matRad"
issue: 6
volume: 46
year: 2017
20 changes: 18 additions & 2 deletions MatRad_Config.m
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@
% Therefore its constructor is private
% For instantiation, use the static MatRad_Config.instance();

obj.matRadRoot = fileparts(mfilename('fullpath'));
addpath(genpath(obj.matRadRoot));

%Set Version
obj.getEnvironment();
obj.matRad_version = matRad_version();

obj.matRadRoot = fileparts(mfilename('fullpath'));

%Configure Environment
obj.configureEnvironment();

%Just to catch people messing with the properties in the file
if ~isempty(obj.writeLog) && obj.writeLog
Expand All @@ -74,6 +78,11 @@
%Call the reset function for remaining inatialization
obj.reset();
end

function delete(~)
%might not be desired by users
%rmpath(genpath(matRad_cfg.matRadRoot));
end

function displayToConsole(obj,type,formatSpec,varargin)
%displayToConsole lowest-level logging function for matRad.
Expand Down Expand Up @@ -299,6 +308,13 @@ function getEnvironment(obj)

end
end

function configureEnvironment(obj)
if obj.isOctave
struct_levels_to_print(0); %Disables full printing of struct array fields
warning("off","Octave:data-file-in-path"); %Disables warning of loading patients from the data folder
end
end
end

methods(Static)
Expand Down
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
[![Contributors](https://img.shields.io/github/contributors/e0404/matRad)](https://github.com/e0404/matRad/graphs/contributors)
[![GitPitch](https://gitpitch.com/assets/badge.svg)](https://gitpitch.com/e0404/matRad/master)

[![TravisCI Build Status](https://travis-ci.org/e0404/matRad.svg?branch=dev)](https://travis-ci.org/e0404/matRad)
[![Azure Pipelines Build Status](https://dev.azure.com/e0404/matRad/_apis/build/status/e0404.matRad?branchName=dev)](https://dev.azure.com/e0404/matRad)
[![GitHub Build Status](https://github.com/e0404/matRad/actions/workflows/tests.yml/badge.svg)](https://github.com/e0404/matRad/actions/workflows/tests.yml)
[![Azure Pipelines Build Status](https://dev.azure.com/e0404/matRad/_apis/build/status/e0404.matRad)](https://dev.azure.com/e0404/matRad)

DOIs:
- General DOI: [![DOI](https://zenodo.org/badge/doi/10.5281/zenodo.3879615.svg)](https://doi.org/10.5281/zenodo.3879615)
Expand Down Expand Up @@ -104,9 +104,16 @@ You can cite specific versions of matRad in your work! For example, Here is the

[![DOI](https://zenodo.org/badge/29671667.svg)](https://zenodo.org/badge/latestdoi/29671667)

# Funding Sources
matRad developments (on this branch) were (in parts) funded by:
- Grant No. BA 2279/3-1 (Project No. 265744405) from the German Research Foundation (DFG)
- Grant No. 70113094 from the German Cancer Aid
- Grant No. WA 4707/1-1 (Project No. 443188743) from the German Research Foundation (DFG)
- Mathworks Academic Research Support

---

Copyright 2020 the matRad development team.
Copyright 2022 the matRad development team.

[email protected]

Expand Down
28 changes: 24 additions & 4 deletions dicom/matRad_convRtssContours2Indices.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,26 @@

dicomCtSlicePos = unique(structure.item(i).points(:,3));

if numel(dicomCtSlicePos) > 1
error('Contour defined over multiple planes\n');
if numel(dicomCtSlicePos) > 1 || isempty(dicomCtSlicePos)
error('Contour defined over multiple planes!');
end

round2 = @(a,b) round(a*10^b)/10^b;
dicomCtSliceThickness = ct.dicomInfo.SliceThickness(round2(ct.dicomInfo.SlicePositions,1)==round2(dicomCtSlicePos,1));

%Sanity check
msg = checkSliceThickness(dicomCtSliceThickness);
if ~isempty(msg)
error('Slice Thickness of slice at %f could not be identified: %s',dicomCtSlicePos,msg);
end

slicesInMatradCt = find(dicomCtSlicePos+dicomCtSliceThickness/2 > ct.z & dicomCtSlicePos-dicomCtSliceThickness/2 <= ct.z);

coords1 = interp1(ct.x,1:ct.cubeDim(2),structure.item(i).points(:,1),'linear','extrap');
coords2 = interp1(ct.y,1:ct.cubeDim(1),structure.item(i).points(:,2),'linear','extrap');

binIn = poly2mask(coords1,coords2,ct.cubeDim(1),ct.cubeDim(2));

slicesInMatradCt = find(dicomCtSlicePos+dicomCtSliceThickness/2 > ct.z & dicomCtSlicePos-dicomCtSliceThickness/2 <= ct.z);

% loop over all slices in matRad ct
for j = 1:numel(slicesInMatradCt)
voiCube(:,:,slicesInMatradCt(j)) = voiCube(:,:,slicesInMatradCt(j)) | binIn;
Expand All @@ -63,3 +69,17 @@
end

indices = find(voiCube(:));

end

function msg = checkSliceThickness(dicomCtSliceThickness)
if isempty(dicomCtSliceThickness)
msg = 'Slice could not be identified (empty)';
elseif ~isscalar(dicomCtSliceThickness)
msg = 'Slice thickness not unique';
elseif ~isnumeric(dicomCtSliceThickness)
msg = 'unexpected value';
else
msg = '';
end
end
50 changes: 23 additions & 27 deletions dicom/matRad_importDicom.m
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
function [ct, cst, pln, resultGUI] = matRad_importDicom( files, dicomMetaBool )
function [ct,cst,pln,stf,resultGUI] = matRad_importDicom( files, dicomMetaBool )
% matRad wrapper function to import a predefined set of dicom files
% into matRad's native data formats
%
% call
% [ct, cst, pln, resultGUI] = matRad_importDicom( files )
% [ct, cst, pln, resultGUI] = matRad_importDicom( files, dicomMetaBool )
% [ct, cst, pln, stf, resultGUI] = matRad_importDicom( files )
% [ct, cst, pln, stf, resultGUI] = matRad_importDicom( files, dicomMetaBool )
%
% input
% files: list of files to be imported (will contain cts and rt
Expand All @@ -16,6 +16,7 @@
% ct: matRad ct struct
% cst: matRad cst struct
% pln: matRad plan struct
% stf: matRad stf struct
% resultGUI: matRad result struct holding data for visualization in GUI
%
% References
Expand All @@ -34,7 +35,7 @@
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

[env, ~] = matRad_getEnvironment();
%[env, ~] = matRad_getEnvironment();

%%
if ~exist('dicomMetaBool','var')
Expand Down Expand Up @@ -85,8 +86,14 @@
for i = 1:numel(structures)
% computations take place here
waitbar(i / steps)
fprintf('creating cube for %s volume...\n', structures(i).structName);
structures(i).indices = matRad_convRtssContours2Indices(structures(i),ct);
fprintf('creating cube for %s volume... ', structures(i).structName);
try
structures(i).indices = matRad_convRtssContours2Indices(structures(i),ct);
fprintf('\n');
catch ME
warning('matRad:dicomImport','could not be imported: %s',ME.message);
structures(i).indices = [];
end
end
fprintf('finished!\n');
close(h)
Expand All @@ -105,6 +112,8 @@
if ~(cellfun(@isempty,files.rtplan(1,:)))
pln = matRad_importDicomRTPlan(ct, files.rtplan, dicomMetaBool);
end
else
pln = struct([]);
end

%% import stf
Expand All @@ -121,6 +130,8 @@
warning('No support for DICOM import of steering information for this modality.');
end
end
else
stf = struct([]);
end

%% import dose cube
Expand All @@ -130,38 +141,23 @@
if ~(cellfun(@isempty,files.rtdose(1,1:2)))
fprintf('loading Dose files \n', structures(i).structName);
% parse plan in order to scale dose cubes to a fraction based dose
if exist('pln','var')
if isfield(pln,'numOfFractions')
resultGUI = matRad_importDicomRTDose(ct, files.rtdose, pln);
end
if exist('pln','var') && ~isempty(pln) && isfield(pln,'numOfFractions')
resultGUI = matRad_importDicomRTDose(ct, files.rtdose, pln);
else
resultGUI = matRad_importDicomRTDose(ct, files.rtdose);
end
if size(resultGUI) == 0
clear resultGUI;
resultGUI = struct([]);
end
end
else
resultGUI = struct([]);
end

%% put weight also into resultGUI
if exist('stf','var') && exist('resultGUI','var')
if ~isempty(stf) && ~isempty(resultGUI)
resultGUI.w = [];
for i = 1:size(stf,2)
resultGUI.w = [resultGUI.w; [stf(i).ray.weight]'];
end
end

%% save ct, cst, pln, dose
matRadFileName = [files.ct{1,3} '.mat']; % use default from dicom
[FileName,PathName] = uiputfile('*','Save as...',matRadFileName);
if ischar(FileName)
% delete unnecessary variables
switch env
case 'MATLAB'
clearvars -except ct cst pln stf resultGUI FileName PathName;
case 'OCTAVE'
clear -x ct cst pln stf resultGUI FileName PathName;
end
% save all except FileName and PathName
save([PathName, FileName], '-regexp', '^(?!(FileName|PathName)$).','-v7.3');
end
18 changes: 17 additions & 1 deletion dicom/matRad_importDicomGUI.m
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,23 @@ function import_button_Callback(hObject, eventdata, handles)

% dicomMetaBool: store complete DICOM information and patientName or not
dicomMetaBool = logical(get(handles.checkPatientName,'Value'));
matRad_importDicom(files, dicomMetaBool);
[ct,cst,pln,stf,resultGUI] = matRad_importDicom(files, dicomMetaBool);


% Save file
matRadFileName = [files.ct{1,3} '.mat']; % use default from dicom
[FileName,PathName] = uiputfile('*','Save as...',matRadFileName);
if ischar(FileName)
%Hack to get non-empty variables
varNames = {'ct','cst','pln','stf','resultGUI'};
ix = cellfun(@(s) ~isempty(evalin('caller',s)),varNames);
varNames = varNames(ix);

FileName = fullfile(PathName,FileName);

% save all non-empty variables imported
save(FileName,'-v7.3',varNames{:});
end


% --- Executes on button press in cancel_button.
Expand Down
4 changes: 4 additions & 0 deletions matRad_calcCubes.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@

resultGUI.w = w;

if isfield(dij,'numParticlesPerMU')
resultGUI.MU = (w.*1e6) ./ dij.numParticlesPerMU;
end

% get bixel - beam correspondence
for i = 1:dij.numOfBeams
beamInfo(i).suffix = ['_beam', num2str(i)];
Expand Down
Loading

0 comments on commit aab03e9

Please sign in to comment.