function PlotZProfileOfImageJROI(inputFilePath,stackName,b_readImageJROIs,imageJROIFileName,recordingTime)
% 20170605_Guanghan: read imageJ ROIs and save the ROI intensity data as
% mat file. 
%inputFilePath: the folder path where the tif stack and the imageJ ROI zip
%file are located. 
%stackName: tif stack name; 
%b_readImageJROIs: if process imageJ ROIs or not (default: true)
%imageJROIFileName: zip file name for ROIs from Image J
%recordingTime: time of recording, in minutes.(optional input) 
if nargin == 0
    inputFilePath = '';
    stackName = '';
    b_readImageJROIs = true;
    imageJROIFileName = 'RoiSet.zip';
    recordingTime = 20; % minutes
end
matROIFileName = [stackName(1:end-4),'_',imageJROIFileName(1:end-4),'.mat'];

outputFilePath_dff0 = fullfile(inputFilePath, [matROIFileName(1:end-4),'\']);
if ~exist(outputFilePath_dff0,'dir')
    mkdir(outputFilePath_dff0);
end

stackFullName = fullfile(inputFilePath,stackName);

if (~exist(fullfile(inputFilePath,matROIFileName),'file') )&& (b_readImageJROIs ==0)
    b_readImageJROIs = 1;
    disp('Cannot find the mat ROI file; Read the imageJ ROIs instead');
end
if b_readImageJROIs
    imageJroifileFullName = fullfile(inputFilePath,imageJROIFileName);
    sROI = ReadImageJROI( imageJroifileFullName);
    imgInfo = imfinfo(stackFullName);
    sliceNum = length( imgInfo );
    img1 = imread(stackFullName,1);
    imgHeight = size(img1,1);
    imgWidth = size(img1,2);
    data3D = zeros( imgHeight, imgWidth, sliceNum);
    % read in the images;
    disp('reading frames...');
    tic;
    TiffLink = Tiff(stackFullName,'r');
    h_waitBar = waitbar(0,'Loading stack...');
    for sliceIndx=1:1:sliceNum
        TiffLink.setDirectory(sliceIndx);
        data3D(:,:,sliceIndx) = TiffLink.read();
        waitbar(sliceIndx/sliceNum,h_waitBar);
    end
    close(h_waitBar);
    TiffLink.close();

    toc;
    disp(['stack data sucessfully loaded,', num2str(toc),' seconds']);

   %% read ROI intensity from image stack based on information from imageJ ROI

    nROI = length(sROI);
    matROIarray = cell(nROI,1);
    ROInames = cell(nROI,1);
    [x,y] = meshgrid( 1:1:imgWidth, 1:1:imgHeight );
    roiIntensity = cell(nROI,1);
    intensity = zeros(sliceNum,1);
    for roiIndx = 1:1:nROI
        disp(['Reading ROI',num2str(roiIndx)]);
        
        crrtROI = sROI{roiIndx};
        ROInames{roiIndx} = crrtROI.strName;
        % step1: get the indices of points inside the ROIs;
        if strcmp(crrtROI.strType,'Freehand') || strcmp(crrtROI.strType,'Polygon')
            crrtROIXY  = crrtROI.mnCoordinates;
        elseif strcmp(crrtROI.strType,'Oval')
            xybound = crrtROI.vnRectBounds;
            y1 = xybound(1);
            x1 = xybound(2);
            y2 = xybound(3);
            x2 = xybound(4);
            x0 = (x1 + x2)/2;
            y0 = (y1 + y2)/2;
            a = (x2-x1)/2;
            b = (y2-y1)/2;
            theta2=linspace(0,2*pi,100);
            theta = theta2(:);
            crrtROIXY = [x0+a*cos(theta), y0+b*sin(theta)];
            
        end
        b_XY = inpolygon(x,y, crrtROIXY(:,1),crrtROIXY(:,2) );
        
        intensity(:) = 0;
        for slcIndx = 1:1:sliceNum
            crrtImg = data3D(:,:,slcIndx);
            pxlInten = crrtImg(b_XY);
            intensity(slcIndx) = mean( pxlInten(:));
        end
        roiIntensity{roiIndx} = intensity;
        crrtROI.rawIntensity = intensity;
        if exist('recordingTime','var')
            crrtROI.recordingTime = recordingTime;
            crrtROI.timePoints =  (1:1:sliceNum).*(recordingTime/sliceNum);
        else
            crrtROI.timePoints = 1:1:sliceNum;
        end
        matROIarray{roiIndx} = crrtROI;
        
    end
    save( fullfile(inputFilePath,matROIFileName),'matROIarray' );
    disp('finish Reading ROIs from imageJ, ROI data saved');
end
end

function [sROI] = ReadImageJROI(cstrFilenames)

% ReadImageJROI - FUNCTION Read an ImageJ ROI into a matlab structure
%
% Usage: [sROI] = ReadImageJROI(strFilename)
%        [cvsROIs] = ReadImageJROI(cstrFilenames)
%        [cvsROIs] = ReadImageJROI(strROIArchiveFilename)
%
% This function reads the ImageJ binary ROI file format.
%
% 'strFilename' is the full path to a '.roi' file.  A list of ROI files can be
% passed as a cell array of filenames, in 'cstrFilenames'.  An ImageJ ROI
% archive can be access by providing a '.zip' filename in
% 'strROIArchiveFilename'.  Single ROIs are returned as matlab structures, with
% variable fields depending on the ROI type.  Multiple ROIs are returned as a
% cell array of ROI structures.
%
% The field '.strName' is guaranteed to exist, and contains the ROI name (the
% filename minus '.roi').
%
% The field '.strType' is guaranteed to exist, and defines the ROI type:
% {'Rectangle', 'Oval', Line', 'Polygon', 'Freehand', 'Traced', 'PolyLine',
% 'FreeLine', 'Angle', 'Point', 'NoROI'}.
%
% The field '.vnRectBounds' is guaranteed to exist, and defines the rectangular
% bounds of the ROI: ['nTop', 'nLeft', 'nBottom', 'nRight'].
%
% The field '.nVersion' is guaranteed to exist, and defines the version number
% of the ROI format.
%
% ROI types:
%  Rectangle:
%     .strType = 'Rectangle';
%     .nArcSize         - The arc size of the rectangle's rounded corners
%
%      For a composite, "shape" ROI:
%     .strSubtype = 'Shape';
%     .vfShapeSegments  - A long, complicated vector of complicated shape
%                          segments.  This vector is in the format passed to the
%                          ImageJ ShapeROI constructor.  I won't decode this for
%                          you! :(
%
%  Oval:
%     .strType = 'Oval';
%
%  Line:
%     .strType = 'Line';
%  	.vnLinePoints     - The end points of the line ['nX1', 'nY1', 'nX2', 'nY2']
%
%     With arrow:
%     .strSubtype = 'Arrow';
%     .bDoubleHeaded    - Does the line have two arrowheads?
%     .bOutlined        - Is the arrow outlined?
%     .nArrowStyle      - The ImageJ style of the arrow (unknown interpretation)
%     .nArrowHeadSize   - The size of the arrowhead (unknown units)
%
%  Polygon:
%     .strType = 'Polygon';
%     .mnCoordinates    - An [Nx2] matrix, specifying the coordinates of
%                          the polygon vertices.  Each row is [nX nY].
%
%  Freehand:
%     .strType = 'Freehand';
%     .mnCoordinates    - An [Nx2] matrix, specifying the coordinates of
%                          the polygon vertices.  Each row is [nX nY].
%
%     Ellipse subtype:
%     .strSubtype = 'Ellipse';
%     .vfEllipsePoints  - A vector containing the ellipse control points:
%                          [fX1 fY1 fX2 fY2].
%     .fAspectRatio     - The aspect ratio of the ellipse.
%
%  Traced:
%     .strType = 'Traced';
%     .mnCoordinates    - An [Nx2] matrix, specifying the coordinates of
%                          the line vertices.  Each row is [nX nY].
%
%  PolyLine:
%     .strType = 'PolyLine';
%     .mnCoordinates    - An [Nx2] matrix, specifying the coordinates of
%                          the line vertices.  Each row is [nX nY].
%
%  FreeLine:
%     .strType = 'FreeLine';
%     .mnCoordinates    - An [Nx2] matrix, specifying the coordinates of
%                          the line vertices.  Each row is [nX nY].
%
%  Angle:
%     .strType = 'Angle';
%     .mnCoordinates    - An [Nx2] matrix, specifying the coordinates of
%                          the angle vertices.  Each row is [nX nY].
%
%  Point:
%     .strType = 'Point';
%     .mnCoordinates    - An [Nx2] matrix, specifying the coordinates of
%                          the points.  Each row is [nX nY].
%
%  NoROI:
%     .strType = 'NoROI';
%
% Additionally, ROIs from later versions (.nVersion >= 218) may have the
% following fields:
%
%     .nStrokeWidth     - The width of the line stroke
%     .nStrokeColor     - The encoded color of the stroke (ImageJ color format)
%     .nFillColor       - The encoded fill color for the ROI (ImageJ color
%                          format)
%
% If the ROI contains text:
%     .strSubtype = 'Text';
%     .nFontSize        - The desired font size
%     .nFontStyle       - The style of the font (unknown format)
%     .strFontName      - The name of the font to render the text with
%     .strText          - A string containing the text

% Author: Dylan Muir <muir@hifo.uzh.ch>
% Created: 9th August, 2011
%
% 20140602 Bug report contributed by Samuel Barnes and Yousef Mazaheri
% 20110810 Bug report contributed by Jean-Yves Tinevez
% 20110829 Bug fix contributed by Benjamin Ricca <ricca@berkeley.edu>
% 20120622 Order of ROIs in a ROI set is now preserved
% 20120703 Different way of reading zip file contents guarantees that ROI order
%           is preserved
%

% -- Check arguments

if (nargin < 1)
   disp('*** ReadImageJROI: Incorrect usage');
   help ReadImageJROI;
   return;
end


% -- Check for a cell array of ROI filenames

if (iscell(cstrFilenames))
   % - Read each ROI in turn
   cvsROI = cellfun(@ReadImageJROI, CellFlatten(cstrFilenames), 'UniformOutput', false);
   
   % - Return all ROIs
   sROI = cvsROI;
   return;
   
else
   % - This is not a cell string
   strFilename = cstrFilenames;
   clear cstrFilenames;
end


% -- Check for a zip file

[nul, nul, strExt] = fileparts(strFilename); %#ok<ASGLU>
if (isequal(lower(strExt), '.zip'))
   % - get zp file contents
   cstrFilenames_short = listzipcontents_rois(strFilename);
   
   % - Unzip the file into a temporary directory
   strROIDir = tempname;
   unzip(strFilename, strROIDir);
   
   for (nFileIndex = 1:length(cstrFilenames_short))
      cstrFilenames{1, nFileIndex} = [strROIDir '/' char(cstrFilenames_short(nFileIndex, 1))];
   end
   
   % - Build ROIs for each file
   cvsROIs = ReadImageJROI(cstrFilenames);
   
   % - Clean up temporary directory
   delete([strROIDir filesep '*.roi']);
   rmdir(strROIDir);
   
   % - Return ROIs
   sROI = cvsROIs;
   return;
end


% -- Read ROI

% -- Check file and open
if (~exist(strFilename, 'file'))
   error('ReadImageJROI:FileNotFound', ...
      '*** ReadImageJROI: The file [%s] was not found.', strFilename);
end

fidROI = fopen(strFilename, 'r', 'ieee-be');

% -- Check file magic code
strMagic = fread(fidROI, [1 4], '*char');

if (~isequal(strMagic, 'Iout'))
   error('ReadImageJROI:FormatError', ...
      '*** ReadImageJROI: The file was not an ImageJ ROI format.');
end

% -- Set ROI name
[nul, sROI.strName] = fileparts(strFilename); %#ok<ASGLU>

% -- Read version
sROI.nVersion = fread(fidROI, 1, 'int16');

% -- Read ROI type
nTypeID = fread(fidROI, 1, 'uint8');
fseek(fidROI, 1, 'cof'); % Skip a byte

% -- Read rectangular bounds
sROI.vnRectBounds = fread(fidROI, [1 4], 'int16');

% -- Read number of coordinates
nNumCoords = fread(fidROI, 1, 'uint16');

% -- Read the rest of the header
vfLinePoints = fread(fidROI, 4, 'float32');
nStrokeWidth = fread(fidROI, 1, 'int16');
nShapeROISize = fread(fidROI, 1, 'uint32');
nStrokeColor = fread(fidROI, 1, 'uint32');
nFillColor = fread(fidROI, 1, 'uint32');
nROISubtype = fread(fidROI, 1, 'int16');
nOptions = fread(fidROI, 1, 'int16');
nArrowStyle = fread(fidROI, 1, 'uint8');
nArrowHeadSize = fread(fidROI, 1, 'uint8');
nRoundedRectArcSize = fread(fidROI, 1, 'int16');
sROI.nPosition = fread(fidROI, 1, 'uint32');

% - Seek to get aspect ratio
fseek(fidROI, 52, 'bof');
fAspectRatio = fread(fidROI, 1, 'float32');

% - Seek to after header
fseek(fidROI, 64, 'bof');


% -- Build ROI

switch nTypeID
   case 1
      % - Rectangle
      sROI.strType = 'Rectangle';
      sROI.nArcSize = nRoundedRectArcSize;
      
      if (nShapeROISize > 0)
         % - This is a composite shape ROI
         sROI.strSubtype = 'Shape';
         if (nTypeID ~= 1)
            error('ReadImageJROI:FormatError', ...
               '*** ReadImageJROI: A composite ROI must be a Rectangle type.');
         end
         
         % - Read shapes
         sROI.vfShapes = fread(fidROI, nShapeROISize, 'float32');
      end
      
      
   case 2
      % - Oval
      sROI.strType = 'Oval';
      
   case 3
      % - Line
      sROI.strType = 'Line';
      sROI.vnLinePoints = round(vfLinePoints);
      
      if (nROISubtype == 2)
         % - This is an arrow line
         sROI.strSubtype = 'Arrow';
         sROI.bDoubleHeaded = nOptions & 2;
         sROI.bOutlined = nOptions & 4;
         sROI.nArrowStyle = nArrowStyle;
         sROI.nArrowHeadSize = nArrowHeadSize;
      end
      
      
   case 0
      % - Polygon
      sROI.strType = 'Polygon';
      sROI.mnCoordinates = read_coordinates;
      
   case 7
      % - Freehand
      sROI.strType = 'Freehand';
      sROI.mnCoordinates = read_coordinates;
      
      if (nROISubtype == 3)
         % - This is an ellipse
         sROI.strSubtype = 'Ellipse';
         sROI.vfEllipsePoints = vfLinePoints;
         sROI.fAspectRatio = fAspectRatio;
      end
      
   case 8
      % - Traced
      sROI.strType = 'Traced';
      sROI.mnCoordinates = read_coordinates;
      
   case 5
      % - PolyLine
      sROI.strType = 'PolyLine';
      sROI.mnCoordinates = read_coordinates;
      
   case 4
      % - FreeLine
      sROI.strType = 'FreeLine';
      sROI.mnCoordinates = read_coordinates;
      
   case 9
      % - Angle
      sROI.strType = 'Angle';
      sROI.mnCoordinates = read_coordinates;
      
   case 10
      % - Point
      sROI.strType = 'Point';
      sROI.mnCoordinates = read_coordinates;
      
   case 6
      sROI.strType = 'NoROI';
      
   otherwise
      error('ReadImageJROI:FormatError', ...
         '--- ReadImageJROI: The ROI file contains an unknown ROI type.');
end


% -- Handle version >= 218

if (sROI.nVersion >= 218)
   sROI.nStrokeWidth = nStrokeWidth;
   sROI.nStrokeColor = nStrokeColor;
   sROI.nFillColor = nFillColor;
   sROI.bSplineFit = nOptions & 1;
   
   if (nROISubtype == 1)
      % - This is a text ROI
      sROI.strSubtype = 'Text';
      
      % - Seek to after header
      fseek(fidROI, 64, 'bof');
      
      sROI.nFontSize = fread(fidROI, 1, 'uint32');
      sROI.nFontStyle = fread(fidROI, 1, 'uint32');
      nNameLength = fread(fidROI, 1, 'uint32');
      nTextLength = fread(fidROI, 1, 'uint32');
      
      % - Read font name
      sROI.strFontName = fread(fidROI, nNameLength, 'uint16=>char');
      
      % - Read text
      sROI.strText = fread(fidROI, nTextLength, 'uint16=>char');
   end
end

% - Close the file
fclose(fidROI);


% --- END of ReadImageJROI FUNCTION ---

   function [mnCoordinates] = read_coordinates
      % - Read X and Y coords
      vnX = fread(fidROI, [nNumCoords 1], 'int16');
      vnY = fread(fidROI, [nNumCoords 1], 'int16');
      
      % - Trim at zero
      vnX(vnX < 0) = 0;
      vnY(vnY < 0) = 0;
      
      % - Offset by top left ROI bound
      vnX = vnX + sROI.vnRectBounds(2);
      vnY = vnY + sROI.vnRectBounds(1);

      mnCoordinates = [vnX vnY];
   end

   function [filelist] = listzipcontents_rois(zipFilename)
      
      % listzipcontents_rois - FUNCTION Read the file names in a zip file
      %
      % Usage: [filelist] = listzipcontents_rois(zipFilename)
      
      % - Import java libraries
      import java.util.zip.*;
      import java.io.*;
      
      % - Read file list via JAVA object
      filelist={};
      in = ZipInputStream(FileInputStream(zipFilename));
      entry = in.getNextEntry();
      
      % - Filter ROI files
      while (entry~=0)
         name = entry.getName;
         if (name.endsWith('.roi'))
            filelist = cat(1,filelist,char(name));
         end
         entry = in.getNextEntry();
      end
      
      % - Close zip file
      in.close();
   end


   function [cellArray] = CellFlatten(varargin)
      
      % CellFlatten - FUNCTION Convert a list of items to a single level cell array
      %
      % Usage: [cellArray] = CellFlatten(arg1, arg2, ...)
      %
      % CellFlatten will convert a list of arguments into a single-level cell array.
      % If any argument is already a cell array, each cell will be concatenated to
      % 'cellArray' in a list.  The result of this function is a single-dimensioned
      % cell array containing a cell for each individual item passed to CellFlatten.
      % The order of cell elements in the argument list is guaranteed to be
      % preserved.
      %
      % This function is useful when dealing with variable-length argument lists,
      % each item of which can also be a cell array of items.
      
      % Author: Dylan Muir <dylan@ini.phys.ethz.ch>
      % Created: 14th May, 2004
      
      % -- Check arguments
      
      if (nargin == 0)
         disp('*** CellFlatten: Incorrect usage');
         help CellFlatten;
         return;
      end
      
      
      % -- Convert arguments
      
      if (iscell(varargin{1}))
         cellArray = CellFlatten(varargin{1}{:});
      else
         cellArray = varargin(1);
      end
      
      for (nIndexArg = 2:length(varargin)) %#ok<FORPF>
         if (iscell(varargin{nIndexArg}))
            cellReturn = CellFlatten(varargin{nIndexArg}{:});
            cellArray = [cellArray cellReturn{:}]; %#ok<AGROW>
         else
            cellArray = [cellArray varargin{nIndexArg}]; %#ok<AGROW>
         end
      end
      
      
      % --- END of CellFlatten.m ---
      
   end
end

