Skip to content

Commit

Permalink
Merge pull request #758 from alexcraven/develop
Browse files Browse the repository at this point in the history
Allow loading of individual DICOM data files
  • Loading branch information
HJZollner authored Jul 22, 2024
2 parents 87b32c4 + 3261202 commit d452476
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 32 deletions.
2 changes: 1 addition & 1 deletion GUI/Osprey.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
logoFcn = @()imread('osprey.png', 'BackgroundColor', gui.colormap.Background);
logoBanner = uiw.utility.loadIcon(logoFcn);
% Here the intro banner is created
gui.d = uiw.dialog.About('Name', 'Osprey','Version','2.6.1','Date', 'July 15, 2024',...
gui.d = uiw.dialog.About('Name', 'Osprey','Version','2.6.2','Date', 'July 22, 2024',...
'Timeout', 3,'CustomText', 'Osprey is provided by Johns Hopkins University.',...
'ContactInfo', 'gabamrs@gmail.com','LogoCData', logoBanner);

Expand Down
2 changes: 1 addition & 1 deletion GUI/osp_Toolbox_Check.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
% 2020-05-15: First version of the code.
%% % 1. SAVE OSPREY VERSION%%%
%%% 1. SAVE OSPREY VERSION%%%
OspreyVersion = 'Osprey 2.6.1';
OspreyVersion = 'Osprey 2.6.2';
fprintf(['Timestamp %s ' OspreyVersion ' ' Module '\n'], datestr(now,'mmmm dd, yyyy HH:MM:SS'));
hasSPM = 1; % For the compiled GUI
%% % 2. GET SPMPATH AND TOOLBOXES%%%
Expand Down
2 changes: 1 addition & 1 deletion job/OspreyJob.m
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@
%%% 7. SET FLAGS AND VERSION %%%
MRSCont.flags.didJob = 1;
MRSCont.loadedJob = jobFile;
MRSCont.ver.Osp = 'Osprey 2.6.1';
MRSCont.ver.Osp = 'Osprey 2.6.2';


%%% 8. CHECK IF OUTPUT STRUCTURE ALREADY EXISTS IN OUTPUT FOLDER %%%
Expand Down
108 changes: 85 additions & 23 deletions libraries/FID-A/inputOutput/io_loadspec_dicom.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,97 @@
%Georg Oeltzschner, Johns Hopkins University 2019.
%
% USAGE:
% out=io_loadspec_dicom(folder);
%
% out=io_loadspec_dicom(source);
%
% DESCRIPTION:
% Loads a DICOM (.dcm, .ima) file into matlab structure format.
%
%
% INPUTS:
% filename = Name of a folder with DICOM (.dcm, .ima) data to load.
% source = Name of a folder (or file) with DICOM (.dcm, .ima) data to load.
%
% OUTPUTS:
% out = Input dataset in FID-A structure format.

function out=io_loadspec_dicom(folder);
function out=io_loadspec_dicom(source);

% If path to a .dcm is provided, then extract the folder location:
if ~isfolder(folder) && isfile(folder)
folder =fileparts(folder);
% ARC170724 : Source may be a folder, or an individual file. We later determine
% how this should be interpreted.
if ~isfolder(source) && isfile(source)
[folder,filename,ext] =fileparts(source);
requested_file=[filename ext];
else
folder=source;
requested_file=[];
end

% Create list of complete filenames (incl. path) in the folder
dirFolder = dir(folder);
filesInFolder = dirFolder(~[dirFolder.isdir]);
hidden = logical(ones(1,length(filesInFolder)));
for jj = 1:length(filesInFolder)
for jj = 1:length(filesInFolder)
if strcmp(filesInFolder(jj).name(1),'.')
hidden(jj) = 0;
end
end
filesInFolder = filesInFolder(hidden);%delete hidden files
filesInFolder = fullfile(folder, {filesInFolder.name});
filesInFolder = filesInFolder(hidden);%delete hidden files

if length(filesInFolder)==0
% No files survived. This will not end well.
error([ 'io_loadspec_dicom did not find any files in ' folder ])
end

requested_file_ix=find(strcmp(requested_file,{filesInFolder.name})); % NB, may be empty

if isfolder(folder)
filesInFolder = fullfile(folder, {filesInFolder.name});
else
% this can happen if the function is called with a wildcard, eg /path/to/abc*dcm
filesInFolder = fullfile(dirname(folder), {filesInFolder.name});
end

% ARC170724 : If a single file is specified (rather than a directory), check
% whether this file should be considered in isolation (pre-averaged data) or
% if it should be combined with other items in the folder. We do this by
% inspecting the Series Number header.

if ~isempty(requested_file_ix)
% check header of the first, last and requested items; if Series Number
% does not match, don't try to combine
check_header_ix = unique([1, requested_file_ix, length(filesInFolder) ]);
encountered_series_numbers = [];
encountered_problems = [];

for ix = check_header_ix
try
dh = dicominfo(filesInFolder{ix});
encountered_series_numbers(end+1) = dh.SeriesNumber;
catch
encountered_problems(end+1) = ix;
end
end

encountered_series_numbers=unique(encountered_series_numbers);

if any(encountered_problems == requested_file_ix)

warning([ 'io_loadspec_dicom could not determine SeriesNumber of the requested file: ' source ]);
% in this case, fall back on default behaviour

elseif length(encountered_series_numbers)>1 || length(encountered_problems)>0

% if we found more than one series, OR we found some unreadable files
% (probably non-DICOM), then just retain that one specific file the
% caller originally asked for

if length(encountered_problems)>0
warning([ 'io_loadspec_dicom encountered some non-DICOM data in ' source ]);
end

filesInFolder={source};
end

% in any other scenario, full back on the default behaviour
end

% Get the header of the first file to make some decisions.
DicomHeader = read_dcm_header(filesInFolder{1});
Expand All @@ -41,7 +103,7 @@
seqorig = DicomHeader.seqorig;
else
% deal with missing seqorig field for dicom data load on Siemens Minnesota
% sequences (Auerbach and Deelchand versions, VB17A & VE11C)
% sequences (Auerbach and Deelchand versions, VB17A & VE11C)
if contains(DicomHeader.sequenceFileName, 'slaser_dkd') %Deelchand/Oz
seqorig = 'CMRR';
elseif contains(DicomHeader.sequenceFileName, 'eja_svs') %Auerbach/Marjanska
Expand Down Expand Up @@ -80,7 +142,7 @@
end
% Collect all FIDs and sort them into fids array
for kk = 1:length(filesInFolder)

% First, attempt to retrieve the FID from the DICOM header:
infoDicom = dicominfo(filesInFolder{kk});
if isfield(infoDicom, 'SpectroscopyData')
Expand All @@ -95,7 +157,7 @@
fids(:,kk) = dicom_get_spectrum_siemens(fd);
fclose(fd);
end

end


Expand All @@ -115,16 +177,16 @@
else
out.flags.averaged = 0;
end

% Currently, the DICOM recon of the universal sequence is flawed.
% Kick out empty lines here and see if data can be reconstructed.
if strcmp(seqorig, 'Universal') && out.flags.averaged == 0
fids(:,size(fids,2)/2+1:end) = [];
end

% Rearrange into subspecs
fids = reshape(fids,[size(fids,1) size(fids,2)/2 2]);

elseif strcmp(seqtype,'PRESS') || strcmp(seqtype,'STEAM') || strcmp(seqtype,'sLASER')
% If the number of stored FIDs does not match the number of averages
% stored in the DICOM header, the data are averaged.
Expand All @@ -137,9 +199,9 @@

elseif strcmp(seqtype,'HERMES')

out.flags.averaged = 0;
out.flags.averaged = 0;
% Currently, the DICOM recon of the universal sequence is flawed.
% Kick out empty lines here and see if data can be reconstructed.
% Kick out empty lines here and see if data can be reconstructed.
if strcmp(seqorig, 'Universal') && out.flags.averaged == 0
fids(:,size(fids,2)/2+1:end) = [];
end
Expand Down Expand Up @@ -222,7 +284,7 @@

%Find the number of averages. 'averages' will specify the current number
%of averages in the dataset as it is processed, which may be subject to
%change. 'rawAverages' will specify the original number of acquired
%change. 'rawAverages' will specify the original number of acquired
%averages in the dataset, which is unchangeable.
if dims.subSpecs ~=0
if dims.averages~=0
Expand All @@ -244,7 +306,7 @@

%Find the number of subspecs. 'subspecs' will specify the current number
%of subspectra in the dataset as it is processed, which may be subject to
%change. 'rawSubspecs' will specify the original number of acquired
%change. 'rawSubspecs' will specify the original number of acquired
%subspectra in the dataset, which is unchangeable.
if dims.subSpecs ~=0
subspecs=sz(dims.subSpecs);
Expand Down Expand Up @@ -288,8 +350,8 @@
out.fids=fids;
out.specs=specs;
out.sz=sz;
out.ppm=ppm;
out.t=t;
out.ppm=ppm;
out.t=t;
out.spectralwidth=spectralwidth;
out.dwelltime=dwelltime;
out.txfrq=txfrq;
Expand Down
10 changes: 5 additions & 5 deletions utilities/CompileOspreyStandalone.m
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ function CompileOspreyStandalone(OutputDir,SPM12Dir,CreateHBCD, CreateCMD, Creat
'OutputDir',OutputDirHBCD,...
'ExecutableIcon',fullfile(OspreyDir, 'graphics','osprey.gif'),...
'ExecutableSplashScreen',fullfile(OspreyDir, 'graphics','osprey.gif'),...
'ExecutableVersion','2.6.1',...
'ExecutableVersion','2.6.2',...
'ExecutableName','OspreyHBCD',...
'AdditionalFiles',{ fullfile(SPM12Dir),...
fullfile(OspreyDir,'coreg'),...
Expand Down Expand Up @@ -243,7 +243,7 @@ function CompileOspreyStandalone(OutputDir,SPM12Dir,CreateHBCD, CreateCMD, Creat
'OutputDir',OutputDirCmd,...
'ExecutableIcon',fullfile(OspreyDir, 'graphics','osprey.gif'),...
'ExecutableSplashScreen',fullfile(OspreyDir, 'graphics','osprey.gif'),...
'ExecutableVersion','2.6.1',...
'ExecutableVersion','2.6.2',...
'ExecutableName','OspreyCMD',...
'AdditionalFiles',{ fullfile(SPM12Dir),...
fullfile(OspreyDir,'coreg'),...
Expand Down Expand Up @@ -278,7 +278,7 @@ function CompileOspreyStandalone(OutputDir,SPM12Dir,CreateHBCD, CreateCMD, Creat
compiler.package.installer(buildResults,'OutputDir',fullfile(OspreyDir,'OspreyCMD_installer'), 'InstallerName', 'OspreyCMD_install', 'RuntimeDelivery', 'installer',...
'AuthorCompany','The Johns Hopkins University', 'Description', 'Installer for Osprey CMD version',...
'InstallationNotes', 'Thank you for downloading Osprey. This installer will allow you to run the Osprey CMD as a standalone application. Please copy the "basissets" folder into the "application" folder after the installation.',...
'Version', '2.6.1', 'ApplicationName','OspreyCMD')
'Version', '2.6.2', 'ApplicationName','OspreyCMD')
end
end

Expand All @@ -294,7 +294,7 @@ function CompileOspreyStandalone(OutputDir,SPM12Dir,CreateHBCD, CreateCMD, Creat
'OutputDir',OutputDirGUI,...
'ExecutableIcon',fullfile(OspreyDir, 'graphics','osprey.gif'),...
'ExecutableSplashScreen',fullfile(OspreyDir, 'graphics','osprey.gif'),...
'ExecutableVersion','2.6.1',...
'ExecutableVersion','2.6.2',...
'ExecutableName','Osprey',...
'AdditionalFiles',{fullfile(WidgetsDir),...
fullfile(GUILayoutDir),...
Expand Down Expand Up @@ -336,7 +336,7 @@ function CompileOspreyStandalone(OutputDir,SPM12Dir,CreateHBCD, CreateCMD, Creat
compiler.package.installer(buildResults,'OutputDir',fullfile(OutputDirGUI,'OspreyGUI_installer'), 'InstallerName', 'OspreyGUI_install', 'RuntimeDelivery', 'web',...
'AuthorCompany','The Johns Hopkins University', 'Description', 'Installer for Osprey GUI version',...
'InstallationNotes', 'Thank you for downloading Osprey. This installer will allow you to run the Osprey GUI as a standalone application. Please copy the "basissets" folder into the "application" folder after the installation',...
'Version', '2.6.1', 'ApplicationName','OspreyGUI')
'Version', '2.6.2', 'ApplicationName','OspreyGUI')
end
end

Expand Down
2 changes: 1 addition & 1 deletion utilities/osp_CheckRunPreviousModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
end

%Do the toolbox check here
OspreyVersion = 'Osprey 2.6.1';
OspreyVersion = 'Osprey 2.6.2';
hasSPM = 1;
[hasSPM,OspreyVersion ] = osp_Toolbox_Check (module,MRSCont.flags.isGUI);

Expand Down

0 comments on commit d452476

Please sign in to comment.