function obj = readMetadata( obj ) %READMETADATA Read the metadata information and stores it in the object %properties % This function parses the file according to the LSM file specifications, % and stores header and segment information that is hten used to fill all % the metadata fields of the object. % % AUTHOR: Stefano Masneri % Date: 13.3.2017 %open file for reading [obj.lsmPtr, errMsg] = fopen(obj.fileFullPath); if obj.lsmPtr < 0 error(['LSMReader.readMetadata: Could not open file ', obj.fileFullPath, ' - ' errMsg]); end s = dir(obj.fileFullPath); filesize = s.bytes; if filesize > 2^32 obj.bigTiff = true; else obj.bigTiff = false; end %read TIFF header byteOrder = fread(obj.lsmPtr, 2, '*char')'; if ~(strcmp(byteOrder,'II')) %only little endian allowed! error('LSMReader.readMetadata: This is not a correct LSM file'); end fortytwo = fread(obj.lsmPtr, 1, 'uint16', obj.BYTE_ORDER); if fortytwo ~= 42 error('LSMReader.readMetadata: This is not a correct LSM file'); end offsetFirstIFD = fread(obj.lsmPtr, 1, 'uint32', obj.BYTE_ORDER); fseek(obj.lsmPtr, offsetFirstIFD, 'bof'); % Now read the first image directory, the one containing all the metadata imgDir = LSMImageDirectory(); imgDir = imgDir.init(obj.lsmPtr, obj.BYTE_ORDER); infoDirEntry = imgDir.dirEntryArray([imgDir.dirEntryArray.tag] == obj.TIF_CZ_LSMINFO ); % Create the LSMInfo object checking the specific Directory Entry if infoDirEntry.isOffset fseek(obj.lsmPtr, infoDirEntry.value, 'bof'); obj.originalMetadata = LSMInfo(obj.lsmPtr, obj.BYTE_ORDER); else error('LSMReader.readMetadata: CZ_LSMINFO tag should contain offset to metadata') end % Now assign all the ImageIO property obj.channels = obj.originalMetadata.dimensionChannels; obj.stacks = obj.originalMetadata.dimensionZ; obj.time = obj.originalMetadata.dimensionTime; obj.series = obj.originalMetadata.dimensionP; obj.tile = obj.originalMetadata.dimensionM; obj.numTilesRow = length(unique(obj.originalMetadata.tilePositions.YPos)); obj.numTilesCol = length(unique(obj.originalMetadata.tilePositions.XPos)); obj.pixPerTileRow = obj.originalMetadata.dimensionY; obj.pixPerTileCol = obj.originalMetadata.dimensionX; for k = 1:length(obj.originalMetadata.datatype) switch obj.originalMetadata.datatype(k) case 1 obj.datatype{k} = 'uint8'; case 2 obj.datatypeInput = 'uint12'; obj.datatype{k} = 'uint16'; case 3 obj.datatype{k} = 'uint16'; case 5 obj.datatype{k} = 'float'; otherwise error('LSMReader.readMetadata: Unrecognized datatype') end end if length(obj.datatype) == 1 obj.datatype = obj.datatype{1}; end obj.channelInfo = obj.originalMetadata.channelColors; obj.scaleSize = [obj.originalMetadata.voxelSizeY obj.originalMetadata.voxelSizeY obj.originalMetadata.voxelSizeZ]; obj.scaleUnits = {'m', 'm', 'm'}; obj.scaleTime = obj.originalMetadata.timeInterval; if ~isempty(obj.originalMetadata.channelWavelength) obj.wavelengthEm = cell(1, obj.originalMetadata.channelWavelength.numChannels); for k = 1:obj.originalMetadata.channelWavelength.numChannels obj.wavelengthEm{k} = [obj.originalMetadata.channelWavelength.startWavelength(k) ... obj.originalMetadata.channelWavelength.endWavelength(k)]; end end try findON = find(strcmpi(obj.originalMetadata.scanInformation.entries, 'ENTRY_OBJECTIVE')); obj.objectiveName = obj.originalMetadata.scanInformation.entries(findON, 2); obj.objectiveName = obj.objectiveName{1}; catch % do nothing end % parse the objective name to extract magnification, numerical aperture and % refractive medium if ~isempty(strfind(obj.objectiveName, 'x/')) pieces = strsplit(obj.objectiveName, ' '); myPos = find(~cellfun(@isempty,strfind(pieces, 'x/'))); magNA = pieces{myPos}; magNA = strsplit(magNA, '/'); obj.objectiveMagnification = magNA{1}; obj.NA = magNA{2}; rm = lower(pieces{myPos + 1}); switch rm case 'w' obj.refractiveMedium = 'Water'; obj.refractiveIndex = 1.33; case 'oil' obj.refractiveMedium = 'Oil'; obj.refractiveIndex = 1.5; case 'imm' obj.refractiveMedium = 'Imm Korr'; obj.refractiveIndex = nan; otherwise % assume it's air obj.refractiveMedium = 'Air'; obj.refractiveIndex = 1; end end obj.microscopeName = 'LSM ZEISS'; try indZX = find(strcmpi(obj.originalMetadata.scanInformation.entries, 'ZOOM_X')); indZY = find(strcmpi(obj.originalMetadata.scanInformation.entries, 'ZOOM_Y')); indZZ = find(strcmpi(obj.originalMetadata.scanInformation.entries, 'ZOOM_Z')); obj.zoom = [cell2mat(obj.originalMetadata.scanInformation.entries(indZX, 2)), ... cell2mat(obj.originalMetadata.scanInformation.entries(indZY, 2)), ... cell2mat(obj.originalMetadata.scanInformation.entries(indZZ, 2))]; catch end try indexLaserWl = find(strcmpi(obj.originalMetadata.scanInformation.entries, 'wavelength')); obj.wavelengthExc = double(cell2mat(obj.originalMetadata.scanInformation.entries(indexLaserWl, 2))); catch end try indexLP = find(strcmpi(obj.originalMetadata.scanInformation.entries, 'LASER_POWER')); indexLA = find(strcmpi(obj.originalMetadata.scanInformation.entries, 'LASER_ACQUIRE')); lp = cell2mat(obj.originalMetadata.scanInformation.entries(indexLP, 2)); la = cell2mat(obj.originalMetadata.scanInformation.entries(indexLA, 2)); obj.laserPower = [num2str(100*la/lp) '%']; catch end try indexGain = find(strcmpi(obj.originalMetadata.scanInformation.entries, 'DETECTOR_GAIN')); obj.gain = cell2mat(obj.originalMetadata.scanInformation.entries(indexGain, 2)); catch end try indexTP = find(strcmpi(obj.originalMetadata.scanInformation.entries, 'PIXEL_TIME')); obj.timePixel = cell2mat(obj.originalMetadata.scanInformation.entries(indexTP, 2)); catch % do nothing end try indexLP = find(strcmpi(obj.originalMetadata.scanInformation.entries, 'RT_LINEPERIOD')); obj.timeLine = cell2mat(obj.originalMetadata.scanInformation.entries(indexLP, 2)); catch % do nothing end obj.colTilePos = obj.originalMetadata.tilePositions.XPos / obj.scaleSize(2); obj.colTilePos = obj.colTilePos - min(obj.colTilePos); obj.rowTilePos = obj.originalMetadata.tilePositions.YPos / obj.scaleSize(1); obj.rowTilePos = obj.rowTilePos - min(obj.rowTilePos); if length(obj.colTilePos) > 1 obj.tileOverlap = 1 - ((obj.colTilePos(2) - obj.colTilePos(1)) / obj.pixPerTileCol); else obj.tileOverlap = 0; end obj.height = uint32(max(obj.rowTilePos) + obj.pixPerTileRow); obj.width = uint32(max(obj.colTilePos) + obj.pixPerTileCol); end