% export2latex(EPLdata, filename, options)
%
% This function may be used to export numeric data in a latex file for later
% use with, e.g., NumericPlots.sty.
% If the data is provided as an 1xK array, each entry of the array will be exported
% to the file <filename>. Each entry of the array must be a structure which contains
% x, y and ident. x and y must be arrays of the same size MxN. If M>1, each column
% of the array is exported to the file and may later be used by \Data<ident><rm>, where
% <rm> is the roman representation of the column number. If M=1, the data may later
% be used with the latex command \Data<ident> 
%
% EPLdata(1, i).x = x-matrix
% EPLdata(1, i).y = y-matrix
% EPLdata(1, i).ident = identifier (has to be a string without numbers ->
% latex command name)
% EPLdata(1, i).descr = description (not necessary)
% filename = filename (with path, without extension)
% options (optional) define which output is required
%
% function roman.m required to convert a number to its roman representation.
%

% author: Thomas König
% date: 2010/04/01
% ed. by Pfeffer Andreas July 2010 ->Axis nearly tight -> xMaxAxis,xMinAxis,... added
% 2010/08/03 Thomas König: Options added
%
% Copyright 2010 Thomas König, Alexander Michel
%
% This file is part of NumericPlots.
%
% NumericPlots is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% any later version.
% 
% NumericPlots is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with NumericPlots.  If not, see <http://www.gnu.org/licenses/>.


function ret = export2latex(EPLdata, filename, options)
    % define standard options
    if ((nargin<3) || ~isfield(options, 'DataBoundaries'))
        % DataBoundaries should be in the output file (xMin, xMax, yMin,
        % yMax)
        options.DataBoundaries = true;
    end
    if ~isfield(options, 'AxisBoundaries')
        % axis boundaries (xMinAxis, xMaxAxis, yMinAxis, yMaxAxis)
        options.AxisBoundaries = false;
    end
    if ~isfield(options, 'AxisBoundariesGap')
        % gap for the axis boundaries in percent of full scale
        options.AxisBoundariesGap = 10;
    end
        
    % open file if possible
    fname = [filename, '.tex'];
    [fid, msg] = fopen(fname, 'wt');
    if fid<0
        display(msg);
        error('Matlab:FileError', ['Could not open the file ', fname '.']);
    end
    
    % write file header
    fprintf(fid, '%% EPLdata written by export2latex\n');
    fprintf(fid, '%% date: %s\n\n', date);
    fprintf(fid, '\\def\\ExpDate{%s}\n', date);
    fclose(fid);
    
    % process data
    for i=1:size(EPLdata,2)
        % Ident='';
        My = size(EPLdata(i).y, 1);
        Mx = size(EPLdata(i).x, 1);
        if ( Mx>1 && Mx~=My )
        	error('Matlab:export2latex', 'EPLdata.x and EPLdata.y must have the same size or EPLdata.x must have one column only');
        end
        if ( Mx==1 )
        	idx_x = ones(1, My);
        else
        	idx_x = 1:Mx;
        end
        
        % data header
        if(isfield(EPLdata(1,i), 'descr'))
            fid = fopen(fname, 'at');
            fprintf(fid, '\\def\\Descr%s{%s}\n', EPLdata(1,i).ident, EPLdata(1,i).descr);
            fclose(fid);
        end
        
        % xMax, xMin, Dx
        fid = fopen(fname, 'at');
        xMax = max(max(EPLdata(1,i).x));
        xMin = min(min(EPLdata(1,i).x));
        
        % axis boundaries
        xMinAxis = xMin-(xMax-xMin)*options.AxisBoundariesGap/100; % -10% axis nearly tight
        xMaxAxis = xMax+(xMax-xMin)*options.AxisBoundariesGap/100; % +10% axis nearly tight 

        
        if (abs(xMax-xMin)<1e-16)
            xMax = 1.0;
            xMin = -1.0;
            fprintf('export2latex - Warning: |xMax-xMin|<1e-16\n');
        end
        DxV = (xMax-xMin)/5;
        NrUnsig = 0;
        while (fix(DxV*10^(NrUnsig)) == 0)
            NrUnsig = NrUnsig+1;
        end
        
        % yMin, yMax, Dy
        yMax = max(max(EPLdata(1,i).y));
        yMin = min(min(EPLdata(1,i).y));
        
        % axis boundaries
        yMinAxis = yMin-(yMax-yMin)*options.AxisBoundariesGap/100; % -10% axis nearly tight 
        yMaxAxis = yMax+(yMax-yMin)*options.AxisBoundariesGap/100; % +10% axis nearly tight 


        if (abs(yMax-yMin)<1e-16)
            yMax = 1.0;
            yMin = -1.0;
            fprintf('export2latex - Warning: |yMax-yMin|<1e-16\n');
        end
        DyV = (yMax-yMin)/5;
        NrUnsig = 0;
        while (fix(DyV*10^(NrUnsig)) == 0)
            NrUnsig = NrUnsig+1;
        end
        
        if options.DataBoundaries
            fprintf(fid, ['\\def\\Data%sXmin{%1.', num2str(NrUnsig), 'f}\n'], EPLdata(1,i).ident, floor(xMin*10^NrUnsig)/(10^NrUnsig));
            fprintf(fid, ['\\def\\Data%sXmax{%1.', num2str(NrUnsig), 'f}\n'], EPLdata(1,i).ident, ceil(xMax*10^NrUnsig)/(10^NrUnsig));
            fprintf(fid, ['\\def\\Data%sYmin{%1.', num2str(NrUnsig), 'f}\n'], EPLdata(1,i).ident, floor(yMin*10^NrUnsig)/(10^NrUnsig));
            fprintf(fid, ['\\def\\Data%sYmax{%1.', num2str(NrUnsig), 'f}\n'], EPLdata(1,i).ident, ceil(yMax*10^NrUnsig)/(10^NrUnsig));
        end
        fprintf(fid, ['\\def\\Data%sDxV{%1.', num2str(NrUnsig), 'f}\n'], EPLdata(1,i).ident, DxV);
        fprintf(fid, ['\\def\\Data%sDyV{%1.', num2str(NrUnsig), 'f}\n'], EPLdata(1,i).ident, DyV);
        if options.AxisBoundaries
            fprintf(fid, ['\\def\\Data%sXminAxis{%1.', num2str(NrUnsig), 'f}\n'], EPLdata(1,i).ident, floor(xMinAxis*10^NrUnsig)/(10^NrUnsig));
            fprintf(fid, ['\\def\\Data%sXmaxAxis{%1.', num2str(NrUnsig), 'f}\n'], EPLdata(1,i).ident, ceil(xMaxAxis*10^NrUnsig)/(10^NrUnsig));
            fprintf(fid, ['\\def\\Data%sYminAxis{%1.', num2str(NrUnsig), 'f}\n'], EPLdata(1,i).ident, floor(yMinAxis*10^NrUnsig)/(10^NrUnsig));
            fprintf(fid, ['\\def\\Data%sYmaxAxis{%1.', num2str(NrUnsig), 'f}\n'], EPLdata(1,i).ident, ceil(yMaxAxis*10^NrUnsig)/(10^NrUnsig));
        end
        fclose(fid);
        
        % write actual data
        for j=1:My
            yyMax = max(EPLdata(1,i).y(idx_x(j),:));
            yyMin = min(EPLdata(1,i).y(idx_x(j),:));
            if (abs(yyMax-yyMin)<1e-16)
                yNrPrecision = 1;
            else
                yNrPrecision = ceil(log10(10000/(yyMax-yyMin)));
            end
            xxMax = max(EPLdata(1,i).x(idx_x(j),:));
            xxMin = min(EPLdata(1,i).x(idx_x(j),:));
            if (abs(xxMax-xxMin)<1e-16)
                xNrPrecision = 1;
            else
                xNrPrecision = ceil(log10(10000/(xxMax-xxMin)));
            end
            NrPrecision = max(yNrPrecision, xNrPrecision);
            fid = fopen(fname, 'at');
            if My > 1; Ident = roman(num2str(j)); else Ident=''; end;
            fprintf(fid, '\\def\\Data%s%s{\n', EPLdata(1,i).ident, Ident);
            fclose(fid);
            dlmwrite(fname, [EPLdata(1,i).x(idx_x(j),:); EPLdata(1,i).y(j,:)]', '-append', 'delimiter', ' ', 'precision', ['%.', num2str(NrPrecision), 'f']);
            fid = fopen(fname, 'at');
            fprintf(fid, '}\n\n');
            fclose(fid);
            %Ident = [Ident, 'D']; %#ok<AGROW>
        end
    end
    ret = 1;
end