-
Notifications
You must be signed in to change notification settings - Fork 0
/
dicom_lst2.m
221 lines (220 loc) · 7.24 KB
/
dicom_lst2.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
%#######################################################################
%
% * DICOM LiST 2 Program *
%
% M-File which reads a series of DICOM directories and
% collects information about the MRI series and DICOM files.
%
% NOTES: 1. Reads Philips MRI DICOM files. May not work with
% other types of images.
%
% 2. Program reads and collects information from the first
% DICOM file header in each series.
%
% 3. The program traps for some, but not all parameters in
% the DICOM file header.
%
% 4. The program looks for subdirectories of the current
% directory that begin with the letter "s". The user
% than selects the subdirectories for processing (typically
% the "Select all" button).
%
% 5. A table of information is displayed to the screen,
% written to a MS-Excel spreadsheet and to a Matlab MAT
% file. The spreadsheet and MAT file are written in the
% same directory as the parent directory. The MAT file
% contains additional variables and all the file names in
% each series and patient position in MRI coordinates.
%
% 06-May-2021 * Mack Gardner-Morse
%
%#######################################################################
%
% Get Series Directories with DICOM Images
%
ddirs = dir('s*');
ddirs = ddirs([ddirs.isdir]');
ddirs = {ddirs.name}';
[isel,ok] = listdlg('ListString',ddirs,'SelectionMode','multiple', ...
'Name','MRI Series Directories','PromptString', ...
'Select MRI Series: ','ListSize',[150 400]);
%
if ok<1
warning(' *** WARNING in dicom_lst2: No series selected!');
return
end
%
ddirs = ddirs(isel);
ns = size(ddirs,1); % Number of series
%
% Loop through the Series and Get Header Information
%
nimages = zeros(ns,1); % Number of DICOM files
afiles = cell(ns,1); % All DICOM file in series
afile1 = cell(ns,1); % First DICOM files in series
afile2 = cell(ns,1); % Last DICOM files in series
%
adur = zeros(ns,2); % Acquisition duration (s)
adurs = cell(ns,1); % Acquisition duration string (mm:ss)
etn = cell(ns,1); % Echo times as numbers for UTE T2 star sequences
ets = cell(ns,1); % Echo times as a string for UTE T2 star sequences
psz = zeros(ns,2); % Rows and columns
im_type = cell(ns,1); % Image type in series
isz = zeros(ns,2); % Width and Height
sthk = zeros(ns,1); % Slice Thickness
sspc = zeros(ns,1); % Spacing Between Slices
pos = zeros(ns,3); % Patient position
pspc = zeros(ns,2); % Pixel Spacing
ptxt = cell(ns,1); % Protocol Name
stxt = cell(ns,1); % Series Description
sl = zeros(ns,1); % Rescale Slope
rinterc = zeros(ns,1); % Rescale Intercept
splt = zeros(ns,1); % Spin lock time (Trigger Time)
sn = zeros(ns,1); % Series number
sdat = datetime(zeros(ns,1),0,0,'Format','dd-MMM-yyyy HH:mm:ss');
%
for k = 1:ns
%
% Get DICOM Files
%
ddir = ddirs{k};
dfiles = dir(fullfile(ddir,'i*.dcm'));
dfiles = dfiles(~[dfiles.isdir]');
nimages(k) = size(dfiles,1);
afiles{k} = {dfiles.name}';
afile1(k) = afiles{k}(1);
afile2(k) = afiles{k}(nimages(k));
%
fnam = afile1{k};
fnam = fullfile(ddir,fnam);
%
% Get DICOM Header Information from Files
%
if exist(fnam,'file')
%
info = dicominfo(fnam);
%
if isfield(info,'AcquisitionDuration')
adur(k) = info.AcquisitionDuration;
adurs{k} = char(duration(seconds(adur(k)),'Format','mm:ss'));
else
adurs{k} = '00:00';
end
if isfield(info,'Rows')
psz(k,:) = [info.Rows info.Columns];
isz(k,:) = [info.Width info.Height];
end
if isfield(info,'SliceThickness')
sthk(k) = info.SliceThickness;
pspc(k,:) = info.PixelSpacing';
sspc(k) = info.SpacingBetweenSlices;
end
if isfield(info,'ImageType')
im_type{k} = info.ImageType;
end
if isfield(info,'ImagePositionPatient')
pos(k,:) = info.ImagePositionPatient';
end
if isfield(info,'RescaleSlope')
sl(k) = info.RescaleSlope;
rinterc(k) = info.RescaleIntercept;
end
ptxt{k} = info.ProtocolName;
stxt{k} = info.SeriesDescription;
sn(k) = info.SeriesNumber;
if isfield(info,'TriggerTime')
splt(k) = info.TriggerTime;
end
if isfield(info,'EchoTrainLength')
n = info.EchoTrainLength;
if n>nimages(k)
n = nimages(k);
end
et = NaN(n,1); % Echo times for this sequence
et(1) = info.EchoTime;
if isfield(info,'Private_2001_1025');
ets{k} = info.Private_2001_1025;
else
ets{k} = num2str(et(1));
end
for m = 2:n
fnam = afiles{k}{m};
fnam = fullfile(ddir,fnam);
if exist(fnam,'file')
info1 = dicominfo(fnam);
et(m) = info1.EchoTime;
else
break;
end
end
etu = unique(et);
idnnan = ~isnan(etu);
etn{k} = etu(idnnan);
if size(etn{k},1)==1&&n>1
idslash = strfind(ets{k},'/');
if ~isempty(idslash)
et1 = eval(ets{k}(1:idslash-1));
det1 = eval(ets{k}(idslash+1:end));
etn{k} = (et1:det1:(n-1)*det1+et1)';
else
etn{k} = eval(ets{k});
end
end
ets{k} = [ets{k} '(' int2str(n) ')'];
end
dat = info.SeriesDate;
tim = info.SeriesTime;
sdat(k) = datetime([dat tim],'InputFormat','yyyyMMddHHmmss.SSSSS');
end
%
end
%
% Get Spin Lock Times from Series Description
%
idvr = contains(stxt,'TSL');
%
splcktc = cellstr(repmat('None',ns,1)); % Cell array for all series
%
if any(idvr)
splckt = extractBetween(stxt(idvr),'TSL','ms'); % Spin lock times as text
splckt = strrep(splckt,'_',' ');
splckt = strtrim(splckt);
splckt = strrep(splckt,' ',',');
splcktc(idvr) = splckt;
end
%
% Include UTE T2star Echo Times
%
idvu = contains(splcktc,'None')&~cellfun(@isempty,ets);
%
if any(idvu)
splcktc(idvu) = ets(idvu);
end
%
% Put Series Data into a Table and Get Column Names
%
colnams = {'Directories','Series#','SeriesDateTime', ...
'SeriesDescription','ProtocolName','ImageType', ...
'AcquisitionDuration','SpinLockTimes','#ofFiles', ...
'FirstFile','LastFile','SliceThickness', ...
'SpacingBetweenSlices','ImageRows','ImageColumns', ...
'Width','Height','ImagePixelX','ImagePixelY', ...
'RescaleSlope','RescaleIntercept'};
t0 = table(string(ddirs),sn,sdat,string(stxt),string(ptxt), ...
string(im_type),string(adurs),string(splcktc),nimages, ...
string(afile1),string(afile2),sthk,sspc,psz(:,1), ...
psz(:,2),isz(:,1),isz(:,2),round(pspc(:,1),3), ...
round(pspc(:,2),3),sl,rinterc,'VariableNames',colnams)
%
% Write Table to Spreadsheet
%
xlsnam = fullfile('dicom_lst2.xlsx');
writetable(t0,xlsnam);
%
% Save MAT File
%
clear ans d0 dat det1 et1 etu idnnan idslash info info1 k l m n tim;
matnam = fullfile('dicom_lst2.mat');
save(matnam);
%
return