function m_list = display_stats( impl_name, rec_list, use_framesns )


% function m_list = display_stats( impl_name, rec_list, [ use_framesns ] )
%
% impl_name: a string, which can be one of those: 'FULL', 'FAST', or 'FASTTDE'.
%
% rec_list: cell array of strings, each string is the name of a recording (e.g. "seq01-1p-0000").
%
% use_framesns (optional): 0 or 1, flag indicating whether we use the cluster-level speech/non-speech 
%   decision (if 0), or the frame-level one (if 1). Default: 0.
%
% m_list: cell array of matrices. In each matrix we capture the numbers
%   that "display_stats" prints on the screen.  


  if nargin < 2
    error( [ mfilename ' needs at least 2 input argument.' ] );
  end
  
  if nargin < 3
    % By default: cluster-level SNS decision
    use_framesns = 0;
  end
  
  switch use_framesns
   case 0
    disp( [ mfilename ': use CLUSTER-LEVEL SNS decision.' ] );
    classify_string = 'classify_cluster_sns';
   case 1
    disp( [ mfilename ': use FRAME-LEVEL SNS decision.' ] );
    classify_string = 'classify_frame_sns';
   otherwise
    error( [ mfilename ': argument "use_framesns" must be 0 or 1.' ] );
  end
  
  % Prepare the output

  m_list = {};
  m_ind  = 0;
  
  % Proportion of frames used for the "restricted" evaluation
  % "restricted" evaluation: only on time frames where the ground-truth location is available for ALL speakers.
  % "allframes" evaluation: only on time frames where the ground-truth location is available for AT LEAST speakers.
  %
  % "proportion": ratio of the two number of frames ( nb. of "restricted" frames ) / ( nb. of "allframes" frames )
  % 
  % See "eval_detloc.m" for more details.
  
  m_ind = m_ind + 1;
  m_list{ m_ind } = [];

  disp( ' ' );
  disp( [ 'ratio restricted / allframes:  ' impl_name ] );
  for a = 1:numel( rec_list )
    
    ratio = [ NaN ];
    
    stat_filename = fullfile( 'DATA', [ 'eval_detloc-' classify_string '-wa_sns_model-' impl_name  '_detect_locate_wrapper-' rec_list{ a } '-result.mat' ] );
    d = dir( stat_filename );
    if numel( d ) == 1
      if d.bytes > 10
	load( stat_filename, 'eval_result' );
	if ~strcmp( eval_result.list.name, rec_list{ a } )
	  error( [ mfilename ': inconsistent recording name.' ] );
	end
	ratio( 1 ) = numel( eval_result.list.restricted.unique_frame_ind ) / numel( eval_result.list.allframes.unique_frame_ind );
      end
    end
    
    % Display
    
    if ~all( isnan( ratio ) )
      disp( [ eval_result.list.name ': ' sprintf( ' %5.4f', ratio ) ] );
    end

    % Store the output

    m_list{ m_ind } = [ m_list{ m_ind }; ratio ];

  end

  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Bias and standard deviation

  disp( ' ' );
  disp( '[restricted] -> bias and std dev in degrees, prior in [0 1]' );

  disp( [ '          &  \multicolumn{3}{c|}{' impl_name '} \\' ] );
  disp( 'Recording & Scenario & Bias & Standard & Correct \\' );
  disp( '          &          &      & deviation & Prior \\' );

  % Prepare the output matrix
  m_ind = m_ind + 1;
  m_list{ m_ind } = [];

  for a = 1:numel( rec_list )

    bias_std_prior = [ NaN NaN NaN ];

    

    

    stat_filename = fullfile( 'DATA', [ 'eval_detloc-' classify_string '-wa_sns_model-' impl_name '_detect_locate_wrapper-' rec_list{ a } '-result.mat' ] );
    d = dir( stat_filename );
    if numel( d ) == 1
      if d.bytes > 10

	load( stat_filename, 'eval_result' );
	if ~strcmp( eval_result.list.name, rec_list{ a } )
	  error( [ mfilename ': inconsistent recording name.' ] );
	end

	gu = eval_result.list.restricted.gu;

	bias_std_prior( 1:3 ) = [ gu.g_mu/pi*180  gu.g_sigma/pi*180 gu.g_prior ];
	
      end
    end

    
    
    % Display
    if ~all( isnan( bias_std_prior ) )
      disp( [ eval_result.list.name ' &  ' sprintf( ' & %6.3f ', bias_std_prior ) ' \\' ] );
    end

    % Store the output
    
    m_list{ m_ind } = [ m_list{ m_ind }; bias_std_prior ];

  end

  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % Distributions of the number of simultaneous correct location estimates
  % Same for "incorrrect"

  %%%     First read them all     %%%

  clear stat_restricted;
  
  clear stat_allframes;

  clear stat_gt;

  for a = 1:numel( rec_list )

    

    stat_filename = fullfile( 'DATA', [ 'eval_detloc-' classify_string '-wa_sns_model-' impl_name '_detect_locate_wrapper-' rec_list{ a } '-result.mat' ] );
    d = dir( stat_filename );
    
    if numel( d ) == 1
      if d.bytes > 10

	load( stat_filename, 'eval_result' );
	if ~strcmp( eval_result.list.name, rec_list{ a } )
	  error( [ mfilename ': inconsistent recording name.' ] );
	end
	stat_restricted( a ) = eval_result.list.restricted;
	stat_allframes( a )  = eval_result.list.allframes;
	stat_gt( a )         = eval_result.list.gt;

      end
    end


  end

  % Make sure all arrays have the same number of elements as "rec_list"
  % If necessary, pad with empty elements
  
  if numel( stat_restricted ) < numel( rec_list )
    stat_restricted( numel( rec_list ) ).gu = [];
  end

  if numel( stat_allframes ) < numel( rec_list )
    stat_allframes( numel( rec_list ) ).gu = [];
  end

  if numel( stat_gt ) < numel( rec_list )
    stat_gt( numel( rec_list ) ).name = [];
  end

  

  % Now we can get the maximum number
  
  stat_n_max = [];
  for a = 1:numel( stat_restricted )
    if ~isempty( stat_restricted( a ).gu )
      stat_n_max = max( [ stat_n_max  stat_restricted( a ).discrete_correct.n_max ] ); 
    end
  end


  %%%     Display: CORRECT     %%%

  disp( ' ' );
  disp( '[ restricted ] distribution of the nb. of SIMULTANEOUS CORRECT location estimates' );

  disp( sprintf( [ '          &  \multicolumn{%d}{c|}{' impl_name '} \\' ], stat_n_max+1 ) );
  disp( [ repmat( ' ', 1, numel( rec_list{ 1 } ) ) sprintf( ' & %5d ', 0:stat_n_max ) ' \\' ] );

  % Prepare the output
  m_ind = m_ind + 1;
  m_list{ m_ind } = [];
  
  for a = 1:numel( rec_list )

    
    stat_v = repmat( NaN, 1, stat_n_max + 1 );

    if ~isempty( stat_restricted( a ).discrete_correct )
      v = stat_restricted( a ).discrete_correct.hcw_norm;
      stat_v(:) = 0;
      stat_v( 1:numel( v ) ) = v(:).';
    end
    
    disp( [ rec_list{ a }  sprintf( ' & %5.2f ', 100 * stat_v )   ' \\' ] );
  
    % Store the output
    
    m_list{ m_ind } = [ m_list{ m_ind }; stat_v  ];

  end

  %%%     repeat for INCORRECT estimates     %%%

  % Now we can get the maximum number
  
  stat_n_max = [];
  for a = 1:numel( stat_restricted )
    if ~isempty( stat_restricted( a ).gu )
      stat_n_max = max( [ stat_n_max  stat_restricted( a ).discrete_incorrect.n_max ] ); 
    end
  end

  disp( ' ' );
  disp( '[ restricted ] distribution of the nb. of SIMULTANEOUS INCORRECT location estimates' );

  disp( sprintf( [ '          &  \multicolumn{%d}{c|}{' impl_name '}  \\' ], stat_n_max+1 ) );
  disp( [ repmat( ' ', 1, numel( rec_list{ 1 } ) ) sprintf( ' & %5d ', 0:stat_n_max ) ' \\' ] );
  
  % Prepare the output
  m_ind = m_ind + 1;
  m_list{ m_ind } = [];

  for a = 1:numel( rec_list )

    
    stat_v = repmat( NaN, 1, stat_n_max + 1 );

    if ~isempty( stat_restricted( a ).discrete_incorrect )
      v = stat_restricted( a ).discrete_incorrect.hcw_norm;
      stat_v(:) = 0;
      stat_v( 1:numel( v ) ) = v(:).';
    end
    
  
    disp( [ rec_list{ a }  sprintf( ' & %5.2f ', 100 * stat_v )  ' \\' ] );

    % Store the output

    m_list{ m_ind } = [ m_list{ m_ind }; stat_v   ];
    
  end


  %%%     Comparison correct/incorrect     %%%

  disp( ' ' );
  disp( '[restricted] comparison in terms of total duration of location estimates (in seconds).' );
  disp( '( correct/incorrect duration = expected number of correct/incorrect location estimates * frameshift in seconds )' );
  disp( 'We also display percentages in brackets (sanity check: should be equal to the "correct prior" displayed above).' );

  disp( [ impl_name ' frameshift_sec: ' sprintf( ' %.5f', [ stat_restricted.frameshift_sec ] ) ] );

  disp( [ '            & \multicolumn{3}{c|}{' impl_name '} \\' ] );
  disp( 'Recording   & Correct duration         & Incorrect duration           & Sum        \\' );
  
  % Prepare the output

  m_ind = m_ind + 1;
  m_list{ m_ind } = [];

  for a = 1:numel( rec_list )
    
    
    stat_v = repmat( NaN, 1, 6 );

    if ~isempty( stat_restricted( a ).frame_n_correct ) & ~isempty( stat_restricted( a ).frame_n_incorrect )

      % Absolute values
      stat_v( 1 ) = sum( stat_restricted( a ).frame_n_correct ) * stat_restricted( a ).frameshift_sec;
      stat_v( 3 ) = sum( stat_restricted( a ).frame_n_incorrect ) * stat_restricted( a ).frameshift_sec;
      stat_v( 5 ) = sum( stat_v( [ 1 3 ] ) );

      % along with percentages in brackets
      stat_v( [ 2 4 ] ) = stat_v( [ 1 3 ] ) / stat_v( 5 );

      stat_v( 6 ) = sum( stat_v( [ 2 4 ] ) ); % Should be 100% -> sanity check
      
    end

    disp( [ rec_list{ a } sprintf( ' & %9.2f (%6.2f%%)', [ stat_v ] * sparse( diag( repmat( [ 1 100 ], 1, numel( [ stat_v ] ) / 2 ) ) ) ) ' \\' ] );
    
    % Store the output

    m_list{ m_ind } = [ m_list{ m_ind }; stat_v  ];

  end


  %%% allframes: show the total number of correct estimates in terms of duration %%%
  
  % (no comparison possible with incorrect estimates because unknown,
  %  unless ratio restricted / allframes = 1.000, in which case there is no difference between restricted and allframes)

  disp( ' ' );
  disp( '[ allframes ] Total duration of correct estimates (in seconds)' );
  disp( 'In brackets we show the ratio duration correct / ground-truthed duration.' );
  disp( '(It may be > 1 when there are a lot of overlaps between speakers.)' );
  disp( [ impl_name ' frameshift_sec: ' sprintf( ' %.5f', [ stat_allframes.frameshift_sec ] ) ] );


  disp( [ 'Recording   & ' impl_name '  \\' ] );

  % Prepare the output

  m_ind = m_ind + 1;
  m_list{ m_ind } = [];

  for a = 1:numel( rec_list )
    
    v = [ NaN NaN ];

    
    
    if ~isempty( stat_allframes( a ).frame_n_correct )

      v( 1 ) = sum( stat_allframes( a ).frame_n_correct ) * stat_allframes( a ).frameshift_sec;
      
      v( 2 ) = v( 1 ) / ( stat_allframes( a ).frameshift_sec * numel( unique( stat_gt( a ).union_frame_ind ) ) );

    end 

    disp( [ rec_list{ a } sprintf( ' & %6.2f ( %5.3f )', v ) ' \\' ] );

    % Store the output

    m_list{ m_ind } = [ m_list{ m_ind }; v ];
    
 end
 
