function tex_filename = reportRankingToPhysiolNeuronsTeXFile(m_bundle, p_bundle, a_crit_db, props)

% reportRankingToPhysiolNeuronsTeXFile - Compare model DB to given physiol criterion and create a report.
%
% Usage:
% tex_filename = reportRankingToPhysiolNeuronsTeXFile(m_bundle, p_bundle, a_crit_db, props)
%
% Description:
%   A LaTeX report is generated 
% following the example in physiol_bundle/matchingRow. The filename contains the neuron
% name, followed by the traceset index as an identifier of pharmacological applications,
% as in gpd0421c_s34. 
%
% Parameters:
%	m_bundle: A model_ct_bundle object.
%	p_bundle: A physiol_bundle object.
%	a_crit_db: The criterion neuron chosen with a matchingRow method.
%	props: A structure with any optional properties.
%	  filenameSuffix: Append this identifier to the TeX filename.
%	  (others passed to rankMatching)
%		
% Returns: 
%	tex_filename: Name of LaTeX file generated.
%
% Example: (see example in physiol_bundle/matchingRow)
%
% See also: tests_db/rankMatching, physiol_cip_traceset/cip_trace, physiol_bundle/matchingRow
%
% $Id$
%
% Author: Cengiz Gunay <cgunay@emory.edu>, 2006/01/18

% Copyright (c) 2007 Cengiz Gunay <cengique@users.sf.net>.
% This work is licensed under the Academic Free License ("AFL")
% v. 3.0. To view a copy of this license, please look at the COPYING
% file distributed with this software or visit
% http://opensource.org/licenses/afl-3.0.php.

if ~exist('props', 'var')
  props = struct;
end

traceset_index = a_crit_db(1, 'TracesetIndex').data;
neuron_name = properTeXLabel(get(getItem(get(p_bundle, 'dataset'), traceset_index), 'id'));
tex_filename = [ neuron_name '_s' num2str(traceset_index) ];

if isfield(props, 'filenameSuffix')
  tex_filename = [ tex_filename props.filenameSuffix ];
end

tex_filename = [ tex_filename '.tex' ];

a_ranked_db = rankMatching(get(m_bundle, 'joined_db'), a_crit_db, props);
ranked_num_rows = dbsize(a_ranked_db, 1);
ranked_num_cols = dbsize(a_ranked_db, 2);

% adjust labels for LaTeX
a_db_id = lower(properTeXLabel(get(a_ranked_db.orig_db, 'id')));
crit_db_id = lower(properTeXLabel(get(a_ranked_db.crit_db, 'id')));

if ranked_num_rows > 0

  % generate plots for 1, 11, .. 41
  plots = plotCompareRanks(m_bundle, p_bundle, a_ranked_db, [1 2 ((1:4)*10 + 1)], props);
  joined_db = plots.joined_db;
  best_trial_num = joined_db(1, 'trial').data;

  % Display raw data traces from dataset
  num_plots = length(plots.trace_d100_plots);

  % Make a full figure with the best matching guy
  short_caption = [ 'Best matching model from ' a_db_id ' to ' crit_db_id '.' ];
  caption = [short_caption ...
	     ' All available raw traces from the criterion cell are shown.' ];
  best_doc = doc_plot(plot_stack([plots.trace_d100_plots{1}, plots.trace_h100_plots{1}], ...
				 [0 3000 -150 80], 'y', ...
				 ['The best match to ' neuron_name ], ...
				 struct('xLabelsPos', 'bottom', 'titlesPos', 'none')), ...
		      caption, [crit_db_id  ' - best matching model from ' a_db_id ], ...
		      struct('floatType', 'figure', 'center', 1, ...
			     'height', '.8\textheight', 'shortCaption', short_caption), ...
		      'best match figure', struct('orient', 'tall'));

  % Also include the fI curves for the best
  short_caption = 'f-I curve of best matching model';
  fIcurve_doc = ...
      doc_plot(plotComparefICurve(m_bundle, best_trial_num, p_bundle, traceset_index, ...
				  struct('shortCaption', short_caption, ...
					 'plotToStats', 1, 'captionToStats', ...
					 'phys. avg.')), ...
	       caption, [crit_db_id  ' - fI curve of best matching model from ' a_db_id ], ...
	       struct('floatType', 'figure', 'center', 1, ...
		      'width', '.7\textwidth', 'shortCaption', short_caption), ...
	       'frequency-current curve', struct);

  % Also include spike shape comparisons for the best
  short_caption = [ 'Spike shapes of best matching model to ' crit_db_id '.' ];
  caption = [ short_caption ];
  crit_trace_d100 = setProp(plots.crit_trace_d100(1), 'quiet', 1);
  crit_spikes = spikes(crit_trace_d100);
  crit_spont_sshape = setProp(getSpike(crit_trace_d100, crit_spikes, 2), 'quiet', 1);
  crit_pulse_sshape = setProp(getPulseSpike(crit_trace_d100, crit_spikes, 2), 'quiet', 1);
  best_trace = setProp(ctFromRows(m_bundle, best_trial_num, 100), 'quiet', 1);
  best_spikes = spikes(best_trace);
  best_spont_sshape = setProp(getSpike(best_trace, best_spikes, 2), 'quiet', 1);
  best_pulse_sshape = setProp(getPulseSpike(best_trace, best_spikes, 2), 'quiet', 1);
  best_sshape_doc = ...
      doc_plot(plot_stack([superposePlots([plotData(best_spont_sshape, 'model'), ...
					   plotData(crit_spont_sshape, 'phys.')], ...
					  {}, '2nd spont. spike'), ...
			   superposePlots([plotData(best_pulse_sshape, 'model'), ...
					   plotData(crit_pulse_sshape, 'phys.')], ...
					  {}, '2nd pulse spike')], [], 'x', ...
			  'Spike shape comparison of best match'), ...
		      caption, [crit_db_id  ' - spike of best matching model from ' a_db_id ], ...
		      struct('floatType', 'figure', 'center', 1, ...
			     'width', '.9\textwidth', 'shortCaption', short_caption), ...
		      'spont spike comparison', struct);

  % Make a full figure with the 2nd best matching guy
  short_caption = [ 'Second best matching model to ' crit_db_id '.' ];
  caption = [ short_caption ...
	     ' All available raw traces from the criterion cell are shown.' ];
  best2_doc = doc_plot(plot_stack([plots.trace_d100_plots{2}, plots.trace_h100_plots{2}], ...
				 [0 3000 -150 80], 'y', ...
				 ['The 2nd best match to ' neuron_name ], ...
				 struct('xLabelsPos', 'bottom', 'titlesPos', 'none')), ...
		      caption, [crit_db_id  ' - 2nd best matching model from ' a_db_id ], ...
		      struct('floatType', 'figure', 'center', 1, ...
			     'height', '.9\textheight', 'shortCaption', short_caption), ...
		      '2nd best match figure', struct('orient', 'tall'));
  
  % Stack rest of matches 
  % prepare a landscape figure with two rows
  % original and 5 matching data traces, +/-100pA traces in separate rows
  % TODO: indicate distances of best and furthest matches
  short_caption = ['Raw traces of the ranked for ' crit_db_id ' .' ];
  caption = [ short_caption ...
	     ' Traces are taken from 5 equidistant matches from the best' ...
	     ' 50 ranks from ' a_db_id '.' ...
	     '  Criterion cell trace is superposed with each model trace.'];

  horiz_props = struct('titlesPos', 'all', 'yLabelsPos', 'left', 'xLabelsPos', 'none');
  d100_row_plot = plot_stack([plots.trace_d100_plots{3:num_plots}], [0 3000 -80 80], 'x', '', ... %+100 pA CIP
			      mergeStructs(struct('xLabelsPos', 'none'), horiz_props));
  h100_row_plot = plot_stack([plots.trace_h100_plots{3:num_plots}], [0 3000 -150 80], 'x', '-100 pA CIP', ...
			     mergeStructs(struct('titlesPos', 'none'), horiz_props));
  
  rest_doc = doc_plot(plot_stack({d100_row_plot, h100_row_plot}, [], 'y', ...
				 ['Best matches to ' neuron_name ], ...
				 struct('titlesPos', 'none')), ...
		      caption, [ crit_db_id ' - top matching models from ' a_db_id ], ...
		      struct('floatType', 'figure', 'center', 1, ...
			     'rotate', 90, 'height', '.9\textheight', ...
			     'shortCaption', short_caption), ...
		      'rest of matches figure');

  clearpage_doc = doc_generate([ '\clearpage%' sprintf('\n') ], 'LaTeX specific page break');

  % Display values of 10 best matches
  if isfield(props, 'num_matches')
    num_best = props.num_matches;
  else
    num_best = 10;
  end
  top_ranks = onlyRowsTests(a_ranked_db, 1:min(num_best, ranked_num_rows), ':', ':');
  short_caption = [ a_db_id ' ranked for ' crit_db_id '.' ];
  caption = [ short_caption ...
	     ' Only ' num2str(num_best) ' best matches are shown.' ];
  if ranked_num_cols > 50
    aspect_props = {'rotate', 0};
  else
    aspect_props = {};
  end
  distancetable_doc = ...
      doc_generate(displayRowsTeX(top_ranks, caption, ...
				  struct('shortCaption', short_caption, ...
					 aspect_props{:})), ...
		   'table of distances from best matching models');

  % Display colored-plot of top 50 matches
  num_best = min(50, ranked_num_rows);
  % TODO: indicate distances of best and furthest matches
  short_caption = ['Individual measure distances color-coded for top matches of ' ...
		   a_db_id  ' ranked for ' crit_db_id '.'];
  caption = [ short_caption ...
	     ' Increasing distance represented with colors starting from ' ...
	     'blue to red. Dark blue=0 STD; light blue=1xSTD; yellow=2xSTD; ' ...
	     'and red=3xSTD difference.' ];
  coloredplot_doc = ...
      doc_plot(plotRowErrors(a_ranked_db, 1:num_best), ...
	       caption, [crit_db_id ' - colorgraph of top ' num2str(num_best) ...
			 ' from ' a_db_id ], ...
	       struct('floatType', 'figure', 'center', 1, ...
		      'width', '\textwidth', 'shortCaption', short_caption), ...
	       'colored distance error plot', struct('orient', 'tall'));

  % Display sorted colored-plot of top 50 matches
  short_caption = [ 'Sorted individual measure distances color-coded for top matches of ' ...
		   a_db_id  ' ranked for ' crit_db_id '.'];
  caption = [ short_caption ...
	     ' Increasing distance represented with colors starting from ' ...
	     'blue to red. Dark blue=0 STD; light blue=1xSTD; yellow=2xSTD; ' ...
	     'and red=3xSTD difference. Measures sorted with overall match quality. ' ];
  sortedcoloredplot_doc = ...
      doc_plot(plotRowErrors(a_ranked_db, 1:num_best, '', struct('sortMeasures', 1)), ...
	       caption, [ crit_db_id ' - sorted colorgraph of top ' num2str(num_best) ...
			 ' from ' a_db_id ], ...
	       struct('floatType', 'figure', 'center', 1, ...
		      'width', '\textwidth', 'shortCaption', short_caption), ...
	       'sorted colored distance error plot', struct('orient', 'tall'));
  
  % Display parameter distributions of 50 best matches
  short_caption = [ 'Parameter distributions of the best ranked for ' crit_db_id '.' ];
  caption = [ short_caption ...
	     ' Only ' num2str(num_best) ' best matches from ' a_db_id ...
	     ' are taken.' ];
  num_best = 50;
  top_ranks = onlyRowsTests(joined_db, 1:min(num_best, ranked_num_rows), ':', ':');
  all_param_cols = true(1, get(top_ranks, 'num_params'));
  all_param_cols(tests2cols(top_ranks, 'trial')) = false;
  p_hists = paramsHists(onlyRowsTests(top_ranks, ':', all_param_cols));
  paramshist_doc = ...
      doc_plot(plot_stack(num2cell(plotEqSpaced(p_hists)), [], 'x', ...
			  ['Parameter distribution histograms of ' num2str(num_best) ...
			   ' best matches' ], ...
			  struct('yLabelsPos', 'left', 'titlesPos', 'none')), ...
	       caption, [ crit_db_id ' - params distribution of top 50 matches to ' ...
			 a_db_id ], ...
	       struct('floatType', 'figure', 'center', 1, ...
		      'width', '0.9\textwidth', 'shortCaption', short_caption), ...
	       'parameter histograms for top 50 matches');

  a_doc_multi = ...
      doc_multi({best_doc, best_sshape_doc, fIcurve_doc, rest_doc, clearpage_doc, distancetable_doc, coloredplot_doc, ...
		 sortedcoloredplot_doc, paramshist_doc, clearpage_doc}, ...
		'comparison report');
else
  a_doc_multi = doc_generate;
end

% TODO: have showParamsList in props to show some arbitrary params
% TODO: create LyX file for convenience.
printTeXFile(a_doc_multi, tex_filename);
