Plotter

1. Introduction

This Octave script (Yes, Octave specifically. From my googling, it seems MATLAB doesn't have a reasonable way to handle command line arguments. Octave has argv.) plots output from the Fortran programs.

2. Command-Line Argument Handling

The script takes 4p + c command line arguments, where c is the total number of curves to plot, and p is the number of separate plots on which to plot them. Usage:

plotter.m [ ( XPLOT | YPLOT ) <filename> <xlabel> <ylabel> [ <legend> ]... ]...
{Usage 2}
function usage_and_exit
    fprintf(stderr(), '%s [ ( XPLOT | YPLOT ) <filename> ', program_name());
    fprintf(stderr(), '<xlabel> <ylabel> [ <legend> ]... ]...\n\n');
    fdisp(stderr(), '`XPLOT` and `YPLOT` starts a new plot with the specified dependent axis.');
    fdisp(stderr(), '<filename> is the image file to output to.');
    fdisp(stderr(), '<xlabel> and <ylabel> specify the axis labels.');
    fdisp(stderr(), '<legend> is a legend entry. `NOP` will skip records.');
    exit(1);
endfunction

Used in section 4

Here the script loops through the arguments and builds up the figures as the relevant arguments are read. If there is a fatal error later in the argument list, plots earlier in the list should be unaffected, since they have already been output. read_fortran_line is implemented in the next section.

{Argument Handling 2}
args = argv(); % Cell array of arguments
independent = read_fortran_line(); % Read independent values
i_in_plot = 1; % Keeps track of which field we're on
dependent_axis = ''; % 'X' or 'Y'
filename = '';
x_label = '';
y_label = '';
legend_array = {}; % Cell array of legend items
for i = 1:(nargin+1)
    if i == nargin+1 || strcmp(args{i}, 'XPLOT') || strcmp(args{i}, 'YPLOT')

        {Prepare New Figure, 2}

    elseif i == 1

        fdisp(stderr(), 'ERROR: The first argument must be either XPLOT or YPLOT.');
        usage_and_exit();

    elseif i_in_plot == 2

        filename = args{i};

    elseif i_in_plot == 3

        x_label = args{i};

    elseif i_in_plot == 4

        y_label = args{i};

    else

        {Plot Curve, 2}

    endif

    i_in_plot = i_in_plot + 1;
end

Used in section 4

When a new figure is created, the previous one is saved if it exists, and the figure-specific variables are reset.

{Prepare New Figure 2}
if i > 1
    if i_in_plot < 4
        fdisp(stderr(), 'ERROR: Early termination of plot specification.');
    endif
    % Apply saved figure adornments
    xlabel(x_label);
    ylabel(y_label);
    legend(legend_array);
    printf('SAVED %s\n', filename);
    saveas(gcf(), filename); % Output current figure to file
endif
if i == nargin+1
    break % End of arguments
endif
% Create new invisible plot, set current
figure('visible', 'off', 'paperposition', [0.25, 2.5, 9.0, 6.0]);
hold on;
% Reset for new plot
i_in_plot = 1;
dependent_axis = args{i}(1); % First character of the arg ('X' or 'Y')
filename = '';
legend_array = {};

Plotting a curve is as simple as reading the dependent values and calling plot.

{Plot Curve 2}
if strcmp(args{i}, 'NOP')
    read_fortran_line(); % Skip
else
    legend_array{length(legend_array) + 1} = args{i}; % Append to legend
    dependent = read_fortran_line(); % Read dependent values
    %color = prism(i_in_plot - 4)((i_in_plot - 4),1:3);
    color = sqrt(rainbow(8)(mod(i_in_plot-5, 8) + 1, 1:3) * 0.9);
    yellowness = color(1) + color(2) - color(3) - 0.5;
    if yellowness > 1
        color /= yellowness;
    endif
    if dependent_axis == 'X'
        plot(dependent, independent, 'color', color);
    else
        plot(independent, dependent, 'color', color);
    endif
endif

3. Standard Input Handling

The script takes in c+1 lines of space-separated reals in scientific notation. The first is for the independent variable array, and the subsequent lines are for the dependent variable arrays to plot. Important: the first value of each line is ignored.

{Input Handler 3}
function values = read_fortran_line
    line = fgetl(stdin()); % Retrieve the next line of standard input
    values = sscanf(line, '%e'); % Find all reals in line
    values = values(2:length(values)); % Remove first value
endfunction

Used in section 4

4. File Outline

{plotter.m 4}
{Usage, 2}

{Input Handler, 3}

{Argument Handling, 2}

Previous ChapterNext Chapter