This repository has been archived by the owner. It is now read-only.
Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
ImageIO/+imageIO/@CZIReader/readRawMetadataSegm.m
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
311 lines (287 sloc)
9.68 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function obj = readRawMetadataSegm( obj ) | |
%READMETADATASEGM Read metadata for segment of type ZISRAWMETADATA | |
% Extract information from ZISRAWMETADATA segments. The first part of the | |
% segment contains the header, namely the size of the XML and the size of | |
% the Attachment. After that there is the xml field and the optional | |
% attachment field | |
% | |
% AUTHOR: Stefano Masneri | |
% Date: 13.10.2016 | |
% Get xml info | |
xmlSize = int32(fread(obj.cziPtr, 1, 'int32')); | |
attSize = int32(fread(obj.cziPtr, 1, 'int32')); % currently unused | |
empty = int32(fread(obj.cziPtr, 62, 'int32')); % spare space | |
% Read xml | |
xmlData = fread(obj.cziPtr, xmlSize, '*char')'; | |
% Convert to struct | |
metadataStruct = xml2struct(xmlData); | |
obj.originalMetadata = metadataStruct; | |
% Now we have an incredibly nested structure. go through all the fields | |
% and try to extract all the metadata info from it | |
top = metadataStruct.ImageDocument.Metadata; | |
% The field "Version" is not of interest, it will be ignored for the | |
% moment | |
%% The field "Information" contains several important metadata | |
% Microscope Info | |
microscopeInfo = top.Information.Instrument; | |
try | |
obj.microscopeName = microscopeInfo.Microscopes.Microscope.System.Text; | |
catch | |
disp('Microscope name not available') | |
end | |
try | |
obj.objectiveName = microscopeInfo.Objectives.Objective.Manufacturer.Model.Text; | |
catch | |
disp('Objective name not available') | |
end | |
try | |
obj.NA = str2double(microscopeInfo.Objectives.Objective.LensNA.Text); | |
catch | |
disp('Numerical aperture info not available') | |
end | |
try | |
obj.objectiveMagnification = str2double(microscopeInfo.Objectives.Objective.NominalMagnification.Text); | |
catch | |
disp('Objective Magnification info not available') | |
end | |
try | |
obj.objectiveNA = str2double(microscopeInfo.Objectives.Objective.LensNA.Text); | |
catch | |
disp('Objective NA info not available') | |
end | |
try | |
obj.refractiveMedium = microscopeInfo.Objectives.Objective.Immersion.Text; | |
if strcmpi(obj.refractiveMedium, 'Air') | |
obj.refractiveIndex = 1; | |
elseif strcmpi(obj.refractiveMedium, 'W') || strcmpi(obj.refractiveMedium, 'Water') | |
obj.refractiveIndex = 1.33; | |
elseif strcmpi(obj.refractiveMedium, 'Oil') | |
obj.refractiveIndex = 1.518; | |
end | |
catch | |
disp('Refraction media info not available') | |
end | |
% try | |
% % we don't know which light source is used... so we don't know the name | |
% % of the structure either! | |
% obj.wavelengthExc = []; | |
% lightSrc = microscopeInfo.LightSources.LightSource; | |
% for k = 1:length(lightSrc) | |
% lst = lightSrc{k}.LightSourceType; | |
% fn = fieldnames(lst); | |
% obj.wavelengthExc = [obj.wavelengthExc, str2double(lst.(fn{1}).Wavelength.Text)]; | |
% end | |
% catch | |
% disp('Excitation wavelength info not available') | |
% end | |
try | |
ChanInfo = top.Information.Image.Dimensions.Channels.Channel; | |
numCh = length(ChanInfo); | |
obj.wavelengthExc = cell(1, numCh); | |
obj.wavelengthEm = cell(1, numCh); | |
obj.zoom = cell(1, numCh); | |
obj.gain = nan(1, numCh); | |
obj.timePixel = nan(1, numCh); | |
obj.timeLine = nan(1, numCh); | |
obj.timeFrame = nan(1, numCh); | |
obj.timeStack = nan(1, numCh); | |
for k = 1:length(ChanInfo) | |
if iscell(ChanInfo) | |
currChan = ChanInfo{k}; | |
else | |
currChan = ChanInfo; | |
end | |
try | |
%obj.wavelengthExc{k} = str2double(currChan.ExcitationWavelength.Text); | |
%get all active lasers for current channel | |
numLightSources = numel(currChan.LightSourcesSettings.LightSourceSettings); | |
waveLengthVector = zeros(1,numLightSources); | |
for i = 1:numLightSources | |
if numLightSources == 1 | |
waveLengthVector(i) = str2double(currChan.LightSourcesSettings.LightSourceSettings.Wavelength.Text); | |
else | |
waveLengthVector(i) = str2double(currChan.LightSourcesSettings.LightSourceSettings{i}.Wavelength.Text); | |
end | |
end | |
obj.wavelengthExc{k} = waveLengthVector; | |
clear waveLengthVector numLightSources i | |
catch | |
obj.wavelengthExc{k} = nan; | |
end | |
try | |
%obj.wavelengthEm{k} = str2double(currChan.EmissionWavelength.Text); | |
obj.wavelengthEm{k} = str2double(strsplit(currChan.DetectionWavelength.Ranges.Text,'-')); | |
catch | |
obj.wavelengthEm{k} = nan; | |
end | |
try | |
obj.timePixel(k) = str2double(currChan.LaserScanInfo.PixelTime.Text); | |
catch | |
end | |
try | |
obj.timeLine(k) = str2double(currChan.LaserScanInfo.LineTime.Text); | |
catch | |
end | |
try | |
obj.timeFrame{k} = str2double(currChan.LaserScanInfo.FrameTime.Text); | |
catch | |
end | |
try | |
obj.timeStack{k} = str2double(currChan.LaserScanInfo.StackTime.Text); | |
catch | |
end | |
try | |
obj.zoom{k} = [str2double(currChan.LaserScanInfo.ZoomX.Text), ... | |
str2double(currChan.LaserScanInfo.ZoomX.Text)]; | |
catch | |
obj.zoom{k} = nan; | |
end | |
try | |
obj.gain(k) = str2double(currChan.DetectorSettings.Gain.Text); | |
catch | |
end | |
end | |
if 1 == length(ChanInfo) | |
obj.zoom = obj.zoom{1}; | |
obj.wavelengthEm = obj.wavelengthEm{1}; | |
obj.wavelengthExc = obj.wavelengthExc{1}; | |
end | |
catch | |
end | |
% Image info | |
imgInfo = top.Information.Image; | |
pixType = imgInfo.PixelType.Text; | |
switch pixType | |
case 'Gray8' | |
obj.datatype = 'uint8'; | |
case 'Gray16' | |
obj.datatype = 'uint16'; | |
case 'Gray32Float' | |
obj.datatype = 'double'; | |
case 'Bgr24' | |
obj.datatype = 'uint8'; | |
case 'Bgr48' | |
obj.datatype = 'uint16'; | |
case 'Bgr96Float' | |
obj.datatype = 'float'; | |
case 'Bgra32' | |
obj.datatype = 'uint8'; | |
otherwise | |
% one of Gray64ComplexFloat or Bgr192ComplexFloat | |
warning('CZIReader.readMetadataSegm: Pixel type not supported') | |
end | |
% now the dimensions | |
try | |
obj.channels = str2double(imgInfo.SizeC.Text); | |
catch | |
obj.channels = 1; | |
end | |
try | |
obj.stacks = str2double(imgInfo.SizeZ.Text); | |
catch | |
obj.stacks = 1; | |
end | |
try | |
obj.series = str2double(imgInfo.SizeS.Text); | |
catch | |
obj.series = 1; | |
end | |
try | |
obj.time = str2double(imgInfo.SizeT.Text); | |
catch | |
obj.time = 1; | |
end | |
try | |
obj.tile = str2double(imgInfo.SizeM.Text); | |
catch | |
obj.tile = 1; | |
end | |
obj.pixPerTileRow = str2double(imgInfo.SizeY.Text); % mandatory | |
obj.pixPerTileCol = str2double(imgInfo.SizeX.Text); % mandatory | |
%% The field "Experiment" contains information about the tiles | |
try | |
tileInfo = top.Experiment.ExperimentBlocks.AcquisitionBlock.TilesSetup.PositionGroups.PositionGroup; | |
if iscell(tileInfo) | |
tileInfo = tileInfo{1}; | |
end | |
obj.numTilesRow = str2double(tileInfo.TilesY.Text); | |
obj.numTilesCol = str2double(tileInfo.TilesX.Text); | |
if (obj.numTilesRow * obj.numTilesCol) ~= obj.tile | |
obj.numTilesRow = 1; | |
obj.numTilesCol = 1; | |
warning('CZIReader.readRawMetadataSegm: inconsistent tile info, possible errors ahead!') | |
end | |
obj.tileOverlap = str2double(tileInfo.TileAcquisitionOverlap.Text); | |
if obj.tileOverlap > 1 | |
obj.tileOverlap = obj.tileOverlap / 100; | |
end | |
obj.width = round((obj.numTilesCol - 1) * (1 - obj.tileOverlap) * obj.pixPerTileCol + ... | |
obj.pixPerTileCol); | |
obj.height = round((obj.numTilesRow - 1) * (1 - obj.tileOverlap) * obj.pixPerTileRow + ... | |
obj.pixPerTileRow); | |
catch | |
disp('CZIReader.readRawMetadataSegm: field Experiment not available') | |
% assume single tile | |
obj.height = obj.pixPerTileRow; | |
obj.width = obj.pixPerTileCol; | |
obj.numTilesRow = 1; | |
obj.numTilesCol = 1; | |
obj.tileOverlap = 0; | |
end | |
% Laser power | |
try | |
mts = top.Experiment.ExperimentBlocks.AcquisitionBlock.MultiTrackSetup.TrackSetup; | |
obj.laserPower = cell(1, length(mts)); | |
for k = 1:length(mts) | |
try | |
if iscell(mts) | |
transmissions = mts{k}.Attenuators.Attenuator.Transmissions.Transmission; | |
else | |
transmissions = mts.Attenuators.Attenuator.Transmissions.Transmission; | |
end | |
if length(transmissions) == 1 | |
obj.laserPower{k} = [num2str(100*str2double(transmissions.Text)) '%']; | |
else | |
obj.laserPower{k} = [num2str(100*str2double(transmissions{1}.Text)) '% - ' ... | |
num2str(100*str2double(transmissions{end}.Text)) '%']; | |
end | |
catch % only one value of power | |
if iscell(mts) | |
transmission = mts{k}.Attenuators.Attenuator.Transmission; | |
else | |
transmission = mts.Attenuators.Attenuator.Transmission; | |
end | |
obj.laserPower{k} = [num2str(100*str2double(transmission.Text)) '%']; | |
end | |
end | |
if length(obj.laserPower) == 1 | |
obj.laserPower = obj.laserPower{1}; | |
end | |
catch | |
disp('Laser Power info not available'); | |
end | |
% The field "DisplaySetting" has info related to the Channels | |
ch = top.DisplaySetting.Channels.Channel; | |
if isstruct(ch) | |
ch = {ch}; | |
end | |
for k = 1:length(ch) %check all channels | |
obj.channelInfo = [obj.channelInfo, ChannelInfo(ch{k}, 'CZI')]; | |
end | |
% The field "Scaling" contain info about the pixels physical size | |
scale = top.Scaling.Items.Distance; | |
obj.scaleSize = ones(1,3); | |
for k = 1:length(scale) | |
switch scale{k}.Attributes.Id | |
case 'X' | |
obj.scaleSize(1) = str2double(scale{k}.Value.Text); | |
case 'Y' | |
obj.scaleSize(2) = str2double(scale{k}.Value.Text); | |
case 'Z' | |
obj.scaleSize(3) = str2double(scale{k}.Value.Text); | |
otherwise | |
warning('CZIReader.readRawMetadataSegm: unrecognized dimension for scale') | |
end | |
obj.scaleUnits = {'m', 'm', 'm'}; | |
end | |
end |