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
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
채택된 답변
추가 답변 (0개)
참고 항목
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!