Skip to content

Instantly share code, notes, and snippets.

@kouichi-c-nakamura
Last active November 19, 2018 15:33
Show Gist options
  • Save kouichi-c-nakamura/3e7146b22737d043f8d2408cd1383c86 to your computer and use it in GitHub Desktop.
Save kouichi-c-nakamura/3e7146b22737d043f8d2408cd1383c86 to your computer and use it in GitHub Desktop.
bfTiffComment allows you to extract, inject, indent or validate OME-XML embeeded in an OME-TIFF file or an XML file.
function [xml, res] = bfTiffComment(imgfile, varargin)
% bfTiffComment allows you to extract, inject, indent or validate OME-XML
% embeeded in an OME-TIFF file or an XML file.
%
% SYNTAX
% xml = bfTiffComment(imgfile)
% xml = bfTiffComment(xmlfile)
% xml = bfTiffComment(xmlstr)
% [xml,res] = bfTiffComment(____,'Param',value)
%
%
% INPUT ARGUMENTS
% imgfile a row vector of characters
% A file path for an image (wiht an extention .ome.tif, .ome.tiff, .ome.tf2, .ome.tf8, .ome.btf).
%
% xmlfile a row vector of characters
% A file path for an XML file (.xml).
%
% xmlstr character array
% XML content. Must begin with '<?xml '.
%
% OPTIONAL PARAMETER/VALUE PAIRS
% 'OutXmlFile'
% a row vector of characters | '' (default) | 'auto'
%
% If you specify this, the extracted XML will be saved as an
% XML file. The value must end with '.xml'. In case you specify
% 'NewXML', the XML file will contain the content of the
% newXML.
%
% If you use 'auto' with {'Indent','off'}, the OutXmlFile is
% automatically set; eg. OME-XML of xxxx.ome.tif will be
% exported to xxxx.xml.
%
% If you use 'auto' with {'Indent','on'}, the OutXmlFile is
% automatically set; eg. indented OME-XML of xxxx.ome.tif will
% be exported to xxxx_indented.xml.
%
% 'NewXML' a row vector of characters | '' (default)
% This can be a character vector holding an XML data
% or a file path for an XML file as an input. If this is
% specified, the TiffComment of imgfile will be overwritten
% with the content of NewXML. If you use xmlfile, it will
% result in an error. Note that leading white spaces for
% indentation, tabs and new lines will be removed.
%
% 'Indent' 'off' (default) | 'on'
% If 'on', the output XML will be indented to make
% it more understandable.
%
%
% 'XMLvalidation'
% 'off' (default) | 'on'
% If 'on', the XML will be validated and result will be
% returned as res.
%
% % 'FixGreekMu'
% % 'off' | 'on' (default)
% % If 'on', the greek letter for mu (used for micrometers) will
% % be corrected.
%
% OUTPUT ARGUMENTS
% xml a row vector of characters
% XML extracted from the file imgfile or xmlfile or NewXML.
%
% res a row vector of characters
% The result of XML validation.
%
% EXAMPLES
% xml = bfTiffComment(imgfile) % return OME-XML of imgfile
% xml = bfTiffComment(xmlfile) % return XML of xmlfile
%
% xml = bfTiffComment('img1.ome.tif','Indent','on','OUtXmlFile','img1_indented.xml');
% % save indented OME-XML of 'img1.ome.tif'
%
% REQUIREMENTS
% Bio-Formats MATLAB toolbox
% https://www.openmicroscopy.org/bio-formats/downloads/
%
%
% Written by Kouichi C. Nakamura Ph.D.
% MRC Brain Network Dynamics Unit
% University of Oxford
% [email protected]
% 14-Nov-2018 19:32:46
%
% See also
% bfTiffComment_test
p = inputParser;
p.addRequired('imgfile',@(x) ischar(x) && (isrow(x) && isfile(x)) || startsWith(x,'<?xml '));
p.addParameter('NewXML','',@(x) ischar(x) && isrow(x));
p.addParameter('OutXmlFile','',@(x) ischar(x) && isrow(x));
p.addParameter('Indent','off',@(x) ischar(x) && isrow(x) && ismember(x,{'on','off'}));
p.addParameter('XMLvalidation','off',@(x) ischar(x) && isrow(x) && ismember(x,{'on','off'}));
p.addParameter('FixGreekMu','on',@(x) ischar(x) && isrow(x) && ismember(x,{'on','off'}));
p.parse(imgfile,varargin{:});
outxmlfile = p.Results.OutXmlFile;
Indent = p.Results.Indent;
newXML = p.Results.NewXML;
xmlvalid = p.Results.XMLvalidation;
% fixGreekMu = p.Results.FixGreekMu;
if strcmp(outxmlfile,'auto')
if isfile(imgfile)
switch Indent
case 'off'
outxmlfile = regexprep(imgfile,'(\.ome\.(tif|tiff|tf2|tf8|)|\.xml)$','.xml');
case 'on'
outxmlfile = regexprep(imgfile,'(\.ome\.(tif|tiff|tf2|tf8|)|\.xml)$','_indented.xml');
end
else
error('If you use OutXmlFile = ''-auto'', you need to provide imgfile or xmlfile as the first input argument.')
end
elseif ~isempty(outxmlfile)
assert(endsWith(outxmlfile,'.xml'))
end
%% extraction of OME-XML
autoloadBioFormats = 1;
% load the Bio-Formats library into the MATLAB environment
status = bfCheckJavaPath(autoloadBioFormats);
assert(status, ['Missing Bio-Formats library. Either add bioformats_package.jar '...
'to the static Java path or add it to the Matlab path.']);
% https://github.com/openmicroscopy/bioformats/blob/develop/tools/tiffcomment.bat
% https://github.com/openmicroscopy/bioformats/blob/develop/components/bio-formats-tools/src/loci/formats/tools/TiffComment.java
% https://downloads.openmicroscopy.org/bio-formats/5.1.10/api/loci/formats/tools/TiffComment.html
TC = loci.formats.tools.TiffComment;
if endsWith(imgfile,'.xml')
fid = fopen(imgfile,'r','n','UTF-8');
tline = {};
while isempty(tline) || ~isequal(tline{end},-1)
tline = [tline;{fgets(fid)}];
end
if numel(tline) == 1
xml = tline{1};
else
tline(end) = [];
xml = [tline{:}];
end
fclose(fid);
elseif startsWith(imgfile,'<?xml ')
xml = imgfile;
else
s = javaArray('java.lang.String',1);
s(1) = java.lang.String(imgfile); %#ok<NASGU>
try
xml = evalc('TC.main(s)');
catch mexc1
throw(mexc1)
end
end
% if strcmp(fixGreekMu,'on')
% % replace micron sign with the proper one
% % No need in MATLAB?
%
% xml = regexprep(xml,char(956),char(181));
%
% end
%% Overwrite the header of the image
if ~isempty(newXML)
if contains(imgfile,{'ome.tif','ome.tiff','ome.tf2','ome.tf8','ome.btf'})
if isfile(newXML) && endsWith(newXML,'.xml')
s = javaArray('java.lang.String',3);
s(1) = java.lang.String('-set');
s(3) = java.lang.String(imgfile);
fid = fopen(newXML,'r','n','UTF-8');
tline = {};
while isempty(tline) || ~isequal(tline{end},-1)
tline = [tline;{fgets(fid)}];
end
if numel(tline) == 1
xml = tline{1};
else
tline(end) = [];
xml = [tline{:}];
end
fclose(fid);
xml = regexprep(xml,'^(\s\s\s){+}(?=<)','');
xml = regexprep(xml,'[\r\n\t\b\v]','');
% if strcmp(fixGreekMu,'on')
% % replace micron sign with the proper one
% xml = regexprep(xml,char(956),char(181));
%
% end
tempxmlname = [tempname,'.xml'];
fid = fopen(tempxmlname,'w','n','UTF-8'); %NOTE UTF-8
fprintf(fid,xml);
fclose(fid);
s(2) = java.lang.String(tempxmlname);
TC.main(s); %TODO test
else
% if strcmp(fixGreekMu,'on')
% % replace micron sign with the proper one
% newXML = regexprep(newXML,char(956),char(181));
%
% end
s = javaArray('java.lang.String',2);
s(1) = java.lang.String(imgfile);
s(2) = java.lang.String(newXML);
xml = newXML; % output is the new XML
TC.main(s); %TODO test
end
else
error('imgfile is not a valid OME-TIFF file.')
end
end
%% loci.formats.tools.XMLIndent
% https://github.com/openmicroscopy/bioformats/blob/develop/tools/xmlindent
% https://downloads.openmicroscopy.org/bio-formats/5.1.10/api/loci/formats/tools/XMLIndent.html
% https://github.com/ome/bio-formats-tools/blob/master/src/main/java/loci/formats/tools/XMLIndent.java
if strcmp(Indent,'on')
tempxmlname = [tempname,'.xml'];
fid = fopen(tempxmlname,'w','n','UTF-8'); %NOTE UTF-8
fprintf(fid,xml);
fclose(fid);
x = javaArray('java.lang.String',1);
x(1) = java.lang.String(tempxmlname); %#ok<NASGU>
% https://www.sejuku.net/blog/49981
xml = evalc('loci.formats.tools.XMLIndent.main(x)'); % this read XML but did not indent
end
%% save XML
if ~isempty(outxmlfile)
fid = fopen(outxmlfile,'w','n','UTF-8'); %NOTE UTF-8
fprintf(fid,xml);
fclose(fid);
end
%% loci.formats.tools.XMLValidate
% https://github.com/openmicroscopy/bioformats/blob/develop/tools/xmlvalid
% https://github.com/ome/bio-formats-tools/blob/master/src/main/java/loci/formats/tools/XMLValidate.java
% https://www.openmicroscopy.org/community/viewtopic.php?f=13&t=8623
if strcmp(xmlvalid,'on')
y = javaArray('java.lang.String',1);
y(1) = java.lang.String(imgfile);
res = evalc('loci.formats.tools.XMLValidate.main(y)'); %TODO nothing happens
else
res = '';
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment