Error with dicomwrite: Attribute has wrong data type.

6 次查看(过去 30 天)
Hello! I am trying to anonymize dicom files by loading the original file with dicominfo and dicomread, changing some fields, and then writing the new file. However, I encountered the error below:
Error using dicom_add_attr>validate_data (line 118)
Attribute (7FE0,0010) has wrong data type.
Error in dicom_add_attr (line 103)
attr_str(pos).Data = validate_data(data, attr_str(pos), specificCharacterSet);
Error in dicom_convert_meta_to_attr (line 39)
attr = dicom_add_attr([], tag(1), tag(2), dictionary, specificCharacterSet, data, VR);
Error in dicom_convert_meta_to_attr>encode_item (line 151)
new_attr = dicom_convert_meta_to_attr(attr_names{p}, item_struct, dictionary, txfr, specificCharacterSet);
Error in dicom_convert_meta_to_attr>encode_SQ (line 125)
data = encode_item(SQ_struct.(items{p}), dictionary, txfr, specificCharacterSet);
Error in dicom_convert_meta_to_attr (line 26)
data = encode_SQ(metadata.(attr_name), dictionary, txfr, specificCharacterSet);
Error in dicom_copy_IOD (line 49)
new_attr = dicom_convert_meta_to_attr(attr_name, metadata, dictionary, options.txfr, specificCharacterSet);
Error in dicomwrite>write_message (line 277)
[attrs, status] = dicom_copy_IOD(X, map, ...
Error in dicomwrite (line 208)
[status, options] = write_message(X, filename, map, metadata, options);
I have also tried simply reading in the original file and writing out the new file (without changing any fields) -
>> y = dicomread('original.dcm');
>> x = dicominfo('original.dcm');
>> dicomwrite(y,'new.dcm',x,'WritePrivate',true,'CreateMode','Copy');
- but these actions produced the same error, as did using dicomanon. Any guidance would be much appreciated!
  6 个评论
Ralph Buchert
Ralph Buchert 2021-1-28
Dear Theodore,
thank you so much. Removing IconImageSequence from the header solved my problem in all cases expect one. I'm very happy, thank you so much :-). Below please find my code, perhapy you find it useful.
With very best wishes
Ralph
function numScans = htpAnonymize(searchDir,anonDir,firstImageOnly)
% anonymize MRI dicom scans
% - works on all dicom data in searchDir and all its subdirectories
% - assumes that each directory containes (at most) one series
% - the anonymized serieses are copied to anonDir, one directory per series
% - generates the txt-file "Codes_<date>" in anonDir that lists IDs, the number of
% images in each series, the number of failures per series etc.
% - generates the log-file "AnonLog_<date>" in anonDir
% - ATTENTION: I did not manage to make sure that the last block of the SOPInstanceUID
% of the images belonging to the same sequence are consecutive numbers
% (neither 'keep' nor 'update' seems to work for SOPInstanceUID). As a consequence, some dicom
% viewers might not recognize that the anonymized images belong to the same series,
% although StudyInstanceUID and SeriesInstanceUID are equal for all images
% of the series ('update' works for StudyInstanceUID and SeriesInstanceUID)%
% - seems to work properly in about 90% of the cases.
% In the remaining 10% of the cases, there is either an error or a warning.
% most frequent error: "Attribute (7FE0,0010) has wrong data type" (= PixelData)
% In these cases (use dicomdisp):
% 0097588 2 (7FE0,0010) OW 4096 bytes - PixelData *Binary*
% 0101696 0 (7FE0,0010) OW 131072 bytes - PixelData []
% In 'normal' cases:
% 0009912 0 (7FE0,0010) OW 247808 bytes - PixelData []
% Solution (Theodore Turesky):
% The problem might be related to errorneous color info (suggesting % color but providing gray), try to
% remove IconImageSequence from the header.
% If this does not work, use another tool (e.g.,
% MicroDicom) to read and export the scan. Then try again.
% - if firstImageOnly == true, only the first dicom image in each subdirectory
% is anonymized. This might be usefull to check for errors and warnings
% before processing a large number of series
%
% Ralph Buchert, January 28, 2021, r.buchert@uke.de
%
values.PatientAddress = 'unknown';
if nargin < 1
searchDir = uigetdir('Select directory to be searched for DICOM data (including all subdirectories)');
end
if nargin < 2
anonDir = uigetdir('Select directory to write anonymized DICOM data');
end
if nargin < 3
firstImageOnly = false;
end
% get subdirs of searchDir
subdirs = genpath(searchDir);
semicolon = regexp(subdirs,';');
numSemicolon = max(size(semicolon));
dirs = {subdirs(1:semicolon(1)-1)};
for i = 1:numSemicolon-1
dirs = [dirs; subdirs(semicolon(i)+1:semicolon(i+1)-1)];
end
dirs = [dirs; subdirs(semicolon(numSemicolon)+1:length(subdirs))];
numDirs = size(dirs,1);
% prepare file for scan name codes
fnameCodes = strcat(anonDir,filesep,'Codes',strrep(strrep(datestr(now),' ','-'),':','-'),'.txt');
fid = fopen(fnameCodes,'w');
if fid == -1
error('ERROR(hptAnonymize): cannot open file to list codes\n\n');
end
fprintf(fid,'%s\t%s\t%s\t%s\t%s\t','original','code','numSlices','numFailures','numFailuresUnresolved');
fprintf(fid,'%s\t%s\t%s\t%s\t','manufacturer','model','fieldStrength','acquisitionDate');
fprintf(fid,'%s\t%s\n','sex','age');
fnameLog = strcat(anonDir,filesep,'AnonLog',strrep(strrep(datestr(now),' ','-'),':','-'),'.txt');
eval(['diary ' fnameLog]);
% do the work
numScans = 0;
for i = 1:numDirs
D = dir(dirs{i});
num_files = size(D,1);
numSlices = 0;
numFailures = 0;
numFailuresUnresolved = 0;
for j = 1:num_files
if (D(j).isdir ~= 1)
slice = strcat(dirs{i},filesep,D(j).name);
if firstImageOnly
condition = isdicom(slice) & (numSlices < 1);
else
condition = isdicom(slice);
end
if condition
numSlices = numSlices + 1;
if numSlices == 1
numScans = numScans + 1;
scan = dirs{i}(length(searchDir)+2:length(dirs{i}));
ind = findstr(dirs{i},filesep);
%newScan = sprintf('Scan%04d',str2num(dirs{i}(ind(length(ind)-1)+1:ind(length(ind))-1)));
newScan = sprintf('Scan%04d',numScans);
mkdir(anonDir,newScan);
newDir = strcat(anonDir,filesep,newScan);
values.StudyInstanceUID = dicomuid;
values.SeriesInstanceUID = dicomuid;
values.StudyID = sprintf('4711%04d',numScans);
values.PatientName.FamilyName = newScan;
values.PatientName.GivenName = newScan;
fprintf('\n\nCurrently working on %s\n\n',scan);
hdr = dicominfo(slice);
end
%anonSlice = strcat(newDir,filesep,D(j).name);
anonSlice = strcat(newDir,filesep,newScan,sprintf('Image%04d',numSlices-1),'.dcm');
try
dicomanon(slice,anonSlice,'keep', {'PatientAge', 'PatientSex', 'StudyDescription'},'update',values,'WritePrivate',false);
catch
numFailures = numFailures + 1;
values.IconImageSequence = [];
try
dicomanon(slice,anonSlice,'keep', {'PatientAge', 'PatientSex', 'StudyDescription'},'update',values,'WritePrivate',false);
catch
numFailuresUnresolved = numFailuresUnresolved+1;
end
rmfield(values,'IconImageSequence');
end
end
end
end
if numSlices > 0
fprintf(fid,'%s\t%s\t%d\t%d\t%d\t',scan,newScan,numSlices,numFailures,numFailuresUnresolved);
try
fprintf(fid,'%s\t',hdr.Manufacturer);
catch
fprintf(fid,'%s\t','na');
end
try
fprintf(fid,'%s\t',hdr.ManufacturerModelName);
catch
fprintf(fid,'%s\t','na');
end
try
fprintf(fid,'%3.1f\t',hdr.MagneticFieldStrength);
catch
fprintf(fid,'%s\t','na');
end
try
fprintf(fid,'%s\t',hdr.AcquisitionDate);
catch
fprintf(fid,'%s\t','na');
end
try
fprintf(fid,'%s\t',hdr.PatientSex);
catch
fprintf(fid,'%s\t','na');
end
try
fprintf(fid,'%s\n',hdr.PatientAge);
catch
fprintf(fid,'%s\n','na');
end
end
end
fclose(fid);
diary;
fprintf('\n\nDone\n\n');
end
Theodore Turesky
Theodore Turesky 2021-1-28
编辑:Theodore Turesky 2021-1-28
Looks great, Ralph! Thank you. Also, I want to credit Ross Mair for identifying the color problem and suggesting I remove the problematic tag.

请先登录,再进行评论。

采纳的回答

Theodore Turesky
Theodore Turesky 2021-1-28
>> y = dicomread('original.dcm');
>> x = dicominfo('original.dcm');
>> x.PatientName = 'anon'; %you'll need to do something like this for every header field that you want to anonymize
>> x.IconImageSequence = []; % this is the key line for avoiding the attribute error
>> dicomwrite(y,'new.dcm',x,'WritePrivate',true,'CreateMode','Copy');

更多回答(0 个)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by