%READTIMESERIES   Reads a series/stack of images from disk in one image.
%
% SYNOPSIS
%  out = readtimeseries(basefilename, extension, range, color, verbose)
%
%  basefilename : File name without the running number or full file name
%  extension    : File extension
%  range        : First and last index to read [first last]
%  color        : Do the files contain color information 'no','yes'
%  verbose      : Show diagnostic messages on which files are read
%
% DEFAULTS:
%  extension    : ''
%  range        : []   % All found images are read
%  color        : no
%  verbose      : yes
%
% EXAMPLE:
%  In the directory /data/here, there are 16 files:
%     myfile4.tif,myfile5.tif,myfile006.tif,...myfile020.tif
%  out = readtimeseries('/data/here/myfile','tif')  or equivalent
%  out = readtimeseries('/data/here/myfile012.tif') or equivalent
%  out = readtimeseries('/data/here/myfile*.tif')
%
% SEE ALSO:
%  readim
%
% NOTES:
%  For files like myleica_z004_ch01.tif etc. use
%  readtimeseries('myleica_z*_ch01.tif')
%
%  The given file name can have only one wildcard '*'. The directory
%  name or the extension cannot. The wildcard can be anywhere in the
%  name of the file.

% (C) Copyright 1999-2009               Pattern Recognition Group
%     All rights reserved               Faculty of Applied Physics
%                                       Delft University of Technology
%                                       Lorentzweg 1
%                                       2628 CJ Delft
%                                       The Netherlands
% Bernd Rieger, June 2001.
% March, 2004, renamed D2toD3 to readtimeseries and added more functionality (BR)
% April, 2004, changed filelist to be more flexible, use now find_files
%              instead of num_slices (BR)
% April, 2004, allowing empty range parameter (I'm lazy!). Removed second reading
%              of first input image (Bernd is lazy too!). Provided for the (unlikely)
%              case that the input slices are not RGB. (CL)
% July 2004,   bug fix for readcolor images, changed default to 'tif' (BR)
% July 2004,   filename is browseable (BR)
% September 2004, moved trimming IN to FIND_FILES.M; changed extension parameter to
%                 string, defaulting to '', changed default file name (CL)
% June 2006,   changed global SupressOutput to parameter VERBOSE (CL)
% July 2006,   added support for multiple tiffs in one tiff (BR)
% December 2006, changed readim call due to change in readim/readcolorim (BR)
% March 2007,  added support for 3D tiff file series (BR)
% July 2007,   small bug fix for some 3D tiff files (BR)
% February 2008, rehaul: better overview for reading multiple multi-page TIFF files,
%                removed trick to fool MATLAB into making a larger array, better
%                handling of color images, not using EVAL, etc.
% April 2009,  Made faster by avoiding indexing in dip_image object. Improved
%              FIND_FILES to make file selection more flexible. (CL)


function out=readtimeseries(varargin)

d = struct('menu','File I/O',...
 'display','Read Time Series',...
 'inparams',struct('name',       {'in','ext','range','col','verbose'},...
                   'description',{'Base filename','Extension','Range','Conserve color information?','Verbose?'},...
                   'type',       {'infile','string','array','boolean','boolean'},...
                   'dim_check',  {0,0,{[1,2],[]},0,0},...
                   'range_check',{'*.*','','N',[],[]},...
                   'required',   {1,0,0,0,0},...
                   'default',    {'imser','',[],1,1}...
                    ),...
 'outparams',struct('name',{'out'},...
                    'description',{'Output image'},...
                    'type',{'image'}...
                    )...
 );
if nargin == 1
   s = varargin{1};
   if ischar(s) & strcmp(s,'DIP_GetParamList')
      out = d;
      return
   end
end
try
   [in,ext,range,col,verbose] = getparams(d,varargin{:});
catch
   if ~isempty(paramerror)
      error(paramerror)
   else
      error(firsterr)
   end
end
if isempty(range)
   range = [0,0];
elseif prod(size(range))~=2
   error('The range parameter must be of the form [start ending]');
end
if range(1) > range(2)
   range = range(end:-1:1);
end

fns = find_files(in,ext,range(1),range(2),verbose);
if isempty(fns)
   fns = {in};
end
M = length(fns);

% Read in the image files
tmp = image_read(fns{1},col,verbose);
colsp = colorspace(tmp);
fdim = ndims(tmp{1});
if M==1
   out = tmp;
else
   out = cell(imarsize(tmp));
   N = length(out);
   out(:) = {dip_array(newim([imsize(tmp),M],datatype(tmp{1})))};
   si = substruct('()',[repmat({':'},1,fdim),{1}]);
   for jj=1:N
      out{jj} = subsasgn(out{jj},si,dip_array(tmp{jj}));
   end
   for ii=2:M
      tmp = image_read(fns{ii},col,verbose);
      si.subs{end} = ii;
      for jj=1:N
         out{jj} = subsasgn(out{jj},si,dip_array(tmp{jj}));
      end
   end
   out = dip_image(out);
   if ~isempty(colsp)
      out = colorspace(out,colsp);
   end
end

% Read in one image file
% In case it's a multi-page TIFF file, read in all the images in it.
function out = image_read(fname,col,verbose)
[tmp,M] = readim(fname);
if ~col
   tmp = colorspace(tmp,'grey');
end
if isempty(M)
   M = 1;
else
   M = M.numberOfImages;
end
if M==1
   if verbose
      disp(['Reading file: ',fname]);
   end
   out = tmp;
else
   if verbose
      disp(['Reading multi-page tiff file ',fname,' as 3D image.']);
   end
   out = cell(imarsize(tmp));
   N = length(out);
   out(:) = {dip_array(newim([imsize(tmp),M],datatype(tmp{1})))};
   colsp = colorspace(tmp);
   for jj=1:N
      out{jj}(:,:,1) = tmp{jj};
   end
   for ii=2:M
      tmp = dipio_imagereadtiff(fname,ii-1); % If the file is not a TIFF, numberOfImages is always 1 -- unless we add new file types!
      if ~col
         tmp = colorspace(tmp,'grey');
      end
      for jj=1:N
         out{jj}(:,:,ii) = tmp{jj};
      end
   end
   out = dip_image(out);
   if ~isempty(colsp)
      out = colorspace(out,colsp);
   end
end
