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

Refactor dicom importer #758

Merged
merged 30 commits into from
Oct 9, 2024
Merged

Refactor dicom importer #758

merged 30 commits into from
Oct 9, 2024

Conversation

Raedlr
Copy link
Contributor

@Raedlr Raedlr commented Aug 28, 2024

  • object oriented structure, import handled by matRad_DicomImporter
  • Adapted GUI to work with new Importer
  • scan is part of the importer and output adapted for better compatibility

@wahln wahln requested review from wahln and amitantony and removed request for wahln August 28, 2024 13:08
@wahln wahln assigned wahln and amitantony and unassigned wahln Aug 28, 2024
@wahln wahln added the refactor label Aug 28, 2024
@wahln
Copy link
Contributor

wahln commented Aug 28, 2024

Thanks for the Pull Request!
@amitantony could you do the review?
Also, we should think about a way to run tests on the DICOM import / export. First step could be to take a very small dummy ct / cst / dose, export it with the dicom exporter, and then try to reimport those by script again.

Copy link
Contributor

@amitantony amitantony left a comment

Choose a reason for hiding this comment

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

Overall the PR looks very good and clean 👍 I have given few format and minimal comments, will run some testing before final approval

%
% input
% importFiles: list of files to be imported (will contain cts and rt
% structure set)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above :
you can move the input description to the description of the funtion, descipbe the require properties of input and output object

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've changed the description here c5b44ad

% call
% obj = matRad_createCst(obj)
%
% input
Copy link
Contributor

Choose a reason for hiding this comment

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

you can move the input description to the description of the funtion, descipbe the require properties of input and output object

@@ -993,14 +895,15 @@
end

methods (Access = private)
% SCAN FUNKTION
% SCAN FUNKTION
Copy link
Contributor

Choose a reason for hiding this comment

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

can we rename this to a more descriptive name for the funtion and not just "scan" ?
like "scanFolder" or something

Copy link
Contributor Author

Choose a reason for hiding this comment

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

renamed here 5dcd737

@@ -64,7 +64,13 @@
end

%% compare Bixel width in stf and pln
if ~isfield(pln.propStf,'bixelWidth') || stf(1).bixelWidth ~= pln.propStf.bixelWidth
if isfield(pln.propStf,'bixelWidth') && ischar(stf(1).bixelWidth)
LogVal = strcmp(stf(1).radiationMode, pln.radiationMode);
Copy link
Contributor

Choose a reason for hiding this comment

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

change variable name to match matRad rules and could chnage it to a descriptive name "matchRadiationMode"

end
end

%We need to set one more variable I forgot to mention above
Copy link
Contributor

Choose a reason for hiding this comment

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

clean up the comments 😋

%
% input
% origCt: original CT as matlab 3D array
% origCtInfo: meta information about the geometry of the orgiCt cube
% resolution: target resolution [mm] in x, y, an z direction for the
% new cube
% grid: optional: externally specified grid vector
% doseGrid: optional: externally specified grid vector
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe change from 'doseGrid' to 'importGrid'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was changed in this update c5b44ad

dose.cube = double(dosedata);
% dose.cube = single(dosedata);
obj.importRTDose.dose.cube = double(dosedata);
% importRTDose.dose.cube = single(dosedata);
Copy link
Contributor

Choose a reason for hiding this comment

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

can remove unused lines


% give it an internal name
dose.internalName = currDose{12};
% obj.dose.internalName = obj.currDose{12};%?????
Copy link
Contributor

Choose a reason for hiding this comment

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

whats going on here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I remember that we discussed this, and I still have no idea, what is this for

Copy link
Contributor

Choose a reason for hiding this comment

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

id suggest removing it

@Raedlr
Copy link
Contributor Author

Raedlr commented Sep 6, 2024

matRad_importDicomSteeringParticles* in the last one

obj.stf(i).gantryAngle = obj.pln.propStf.gantryAngles(i);
obj.stf(i).couchAngle = obj.pln.propStf.couchAngles(i);
obj.stf(i).bixelWidth = obj.pln.propStf.bixelWidth;
obj.stf(i).matchRadiationMode = obj.pln.radiationMode;
Copy link
Contributor

Choose a reason for hiding this comment

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

check all files for this name and correct it ( matchRadiationMode)

if numel(res_z) > 1
set(handles.resx_edit,'String',this.importer.importFiles.resx);
set(handles.resy_edit,'String',this.importer.importFiles.resy);
if numel(this.importer.importFiles.resz) > 1
Copy link
Contributor

Choose a reason for hiding this comment

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

In testing, numel(this.importer.importFiles.resz) is >1 if the number of characters in resz (String) is >1,
Will need to implement some other check to see if you have multiple resz entries.

set(handles.resx_edit,'String',res_x);
set(handles.resy_edit,'String',res_y);
set(handles.resx_edit,'String',this.importer.importFiles.resx);
set(handles.resy_edit,'String',this.importer.importFiles.resy);
if numel(res_z) > 1
Copy link
Contributor

Choose a reason for hiding this comment

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

see comment above

matRad/util/matRad_comparePlnStf.m Outdated Show resolved Hide resolved
@amitantony
Copy link
Contributor

final testing required for importing particle therapy plan, then we are ready to go

wahln added 3 commits October 3, 2024 00:16
* temorary directory used for dicom export and reimport
* removed GUI elements from folder scanning
@wahln
Copy link
Contributor

wahln commented Oct 2, 2024

I did a few changes:

  • added helper function to use temporary directory in tests
  • extended the tests to do an export and an actual reimport
  • temorary directory used for dicom export and reimport tests
  • removed GUI elements from folder scanning (I don't want to many boxes opened when we are using the exporter from script!)

In matRad_interpDicomCtCube, there still seems to be an issue in case of SliceThickness being a String in this line:

if(all(abs([origCtInfo(1).PixelSpacing(1),origCtInfo(1).PixelSpacing(2),origCtInfo(1).SliceThickness] - [resolution.x,resolution.y,resolution.z]) < 1e-6))

If this only happens with the data exported from us, then it might either be an exporter error or an import error. The standard suggests a "Decimal String" for the attribute, so its unclear.

Copy link
Contributor

@wahln wahln left a comment

Choose a reason for hiding this comment

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

Not entirely sure if you can always be sure that the imported resz is coming in as a string - str2double will produce NaN if it is already a double.

@@ -65,7 +65,7 @@
% might not been defined for individual files
obj.importCT.ctInfo(i).PixelSpacing = tmpDicomInfo.PixelSpacing;
obj.importCT.ctInfo(i).ImagePositionPatient = tmpDicomInfo.ImagePositionPatient;
obj.importCT.ctInfo(i).SliceThickness = obj.importFiles.resz;
obj.importCT.ctInfo(i).SliceThickness = str2double(obj.importFiles.resz);
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you certain that this is always a string / char array? Because if it is a number, it will become NaN here.

Comment on lines 283 to 295
if ~warnDlgDICOMtagShown && strcmp(allfiles{row,column},defaultPlaceHolder) && (column == 3 || column == 4)

dlgTitle = 'Dicom Tag import';
dlgQuestion = ['matRad_scanDicomImportFolder: Could not parse dicom tag: ' tag '. Using placeholder ' defaultPlaceHolder ' instead. Please check imported data carefully! Do you want to continue?'];
answer = questdlg(dlgQuestion,dlgTitle,'Yes','No', 'Yes');

warnDlgDICOMtagShown = true;

switch answer
case 'No'
matRad_cfg.dispError('Inconsistency in DICOM tags')
end
end
Copy link
Contributor

Choose a reason for hiding this comment

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

This is opening a dialog waiting for an answer. Dialogs should not be opened in the functions (which might also beused from scripts) but in the corresponding GUI piece.

@wahln
Copy link
Contributor

wahln commented Oct 9, 2024

Pushed some fixes to pass octave tests

@wahln wahln merged commit 5d6be04 into e0404:dev Oct 9, 2024
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants