function contour_sequence4 ( xy_filename, u_filename )

%*****************************************************************************80
%
%% contour_sequence4() creates contour plots and PNG files from a sequence of datasets.
%
%  Discussion:
%
%    This program can be used to turn data files into a sequence of PNG
%    images, suitable for an animation.
%
%    Although this program can handle a single input file, its most useful
%    application is in processing many files, with 'consecutive' names, such
%    as "fred01.txt", "fred02.txt", "fred03.txt" and so on.  The user only
%    has to tell the program to process the first file, and it will automatically
%    continue to process files until it reaches the end of the sequence of names.
%
%    The input files:
%    ---------------
%
%    The X and Y input data files store the values of X and Y for points
%    on a regularly spaced grid.  The grid does not have
%    to be evenly spaced, but for this program to work, it must be the case
%    that the (X,Y) points form an M by N grid, and that the value of X or 
%    of Y is constant along a grid line!
%
%    (In other words, a square grid is fine, but a rectangular grid is OK too.
%    A rectangular grid with constant spacing is fine, but a rectangular grid
%    with variable spacing is OK.  But a "wiggly" or curved grid is no good.)
%
%    Each U input data file is assumed to store the value of the
%    associated scalar U.
%
%    Also, the points in the data file must be listed in a reasonable order,
%    either by rows or by columns.
%
%    Internal processing:
%    ===================
%
%    The program has to figure out the grid parameters M and N, and convert
%    the vectors of data X, Y, U into doubly indexed arrays that can be handled
%    by the MATLAB contour routine.  Once the contour plot is displayed, an
%    image of it is saved as a PNG file.
%
%    Once the first file is processed, the routine checks to see if there
%    is a second "consecutive" file, and it so, it is also processed, and 
%    so on, until presumably all files in the sequence have been handled.
%
%  Usage:
%
%    contour_sequence4 ( xy_filename, u_filename )
%
%    Note that a literal filename must be enclosed in single quotes.
%    Thus, a typical invocation might be
%
%      contour_sequence4 ( 'xy.txt', 'u0001.txt' )
%
%    But if you simply say 
%
%      contour_sequence4
%
%    the program will give you a chance to enter the filenames
%    interactively.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    25 December 2018
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    string XY_FILENAME, the name of the XY input file.
%
%    string U_FILENAME, the name of the (first) U input file.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'contour_sequence4():\n' );
  fprintf ( 1, '  MATLAB/Octave version %s\n', version ( ) );
  fprintf ( 1, '  Contours and PNG files of scalar data on a 2D array.\n' );
%
%  If at least one command line argument, it's the X file name.
%
  if ( nargin < 1 )

    fprintf ( 1, '\n' );
    fprintf ( 1, 'contour_sequence4():\n' );
    xy_filename = input ( '  Enter the name of the XY data file:' );

  end

  if ( ~file_exist ( xy_filename ) )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'contour_sequence4(): Fatal error!\n' );
    fprintf ( 1, '  The file "%s" does not exist.\n', x_filename );
    return
  end
%
%  If two command line arguments, the second is the U file name.
%
  if ( nargin < 2 )

    fprintf ( 1, '\n' );
    fprintf ( 1, 'contour_sequence4():\n' );
    u_filename = input ( '  Enter the name of the U data file:' );

  end

  if ( ~file_exist ( u_filename ) )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'contour_sequence4(): Fatal error!\n' );
    fprintf ( 1, '  The file "%s" does not exist.\n', u_filename );
    return
  end
%
%  Save the name of the first input file, and set the name of the first PNG file.
%
  u_root = u_filename;

  png_root = file_name_ext_swap ( u_root, 'png' );
  png_filename = png_root;

  fprintf ( 1, '\n' );
  fprintf ( 1, '  First PNG file will be %s\n', png_root );
%
%  Read the data in the first file.
%
  xy = load ( xy_filename );
  u = load ( u_filename );
%
%  Record the "shape" of the data.  
%  M is the number of records.
%  N is presumably 1.
%
  [ m, n ] = size ( u );
%
%  Try to determine if X or Y is the slowest to vary in the listing.
%
  if ( xy(2,1) == xy(1,1) )
    orientation = 1;
  else
    orientation = 2;
  end
%
%  Try to determine the value of NX and NY.
%
  if ( orientation == 1 )
    ny = 2;
    while ( true )
      if ( xy(ny+1,1) ~= xy(1,1) )
        break;
      end
      ny = ny + 1;
    end
    nx = m / ny;
  elseif ( orientation == 2 )
    nx = 2;
    while ( true )
      if ( xy(nx+1,2) ~= xy(1,2) )
        break;
      end
      nx = nx + 1;
    end
    ny = m / nx;
  end
%
%  We need to read all the U data once, 
%  so we can set values for UMIN and UMAX,
%  so we can specify a single set of contour values that will apply to all frames.
%
  umax = max ( u(1:m,1) );
  umin = min ( u(1:m,1) );

  while ( true )
      
    u_filename = file_name_inc ( u_filename );

    if ( ~file_exist ( u_filename ) )
      break
    end
    
    u = load ( u_filename );

    umax = max ( umax, max ( u(1:m,1) ) );
    umin = min ( umin, min ( u(1:m,1) ) );

  end
%
%  Create the contour plots.
%
  u_filename = u_root;

  frame_num = 0;
%
%  Set the number of contour levels.
%
  udel = ( umax - umin ) / 15;
  v = umin : udel : umax;
%
%  Loop over all files.
%
  while ( true )
      
    u = load ( u_filename );

    if ( orientation == 1 )
      x = reshape ( xy(:,1), nx, ny );
      y = reshape ( xy(:,2), nx, ny );
      u = reshape ( u, nx, ny );
    elseif ( orientation == 2 )
      x = ( reshape ( xy(:,1), ny, nx ) )';
      y = ( reshape ( xy(:,2), ny, nx ) )';
      u = ( reshape ( u, ny, nx ) )';
    end
%
%  Set up a colormap.
%
  colormap ( jet );
%
%  Display a contour plot.
%
%  CONTOURF is pretty nice, but there are some other interesting options.
%
%  CONTOUR does contour LINES.
%  CONTOURF is the same as CONTOUR, but fills the contour regions with colors.
%  CONTOUR3 shows a 3D surface.
%
%  SURF makes a 3D surface, but the colors are not very smooth.
%
%  PCOLOR makes a flat "contour" plot; it doesn't actually make a nice contour plot,
%  but just breaks the picture up into boxes corresponding to each data value,
%  and fills that box with a solid color.  Using a shading option helps a little.
%
%    [ C1, h1 ] = contour ( x, y, u, v );
%
    [ C1, h1 ] = contourf ( x, y, u, v );   
%
%   [ C1, h1 ] = contour3 ( x, y, u, v );
%    surf ( x, y, u );
%    pcolor ( x, y, u );
%
%  CAXIS allows us to force every plot to share the same fixed contour levels.
%
  caxis ( [ umin, umax ] );
%
%  Use this shading option for the SURF or PCOLOR commands to get rid of the
%  black cell box lines and to somewhat smooth out the boxy colors.
%
%    shading ( 'interp' );
%
%  Place a colorbar on the plot.
%
    colorbar ( );
%
%  Label the axes and the plot.
%
    xlabel ( 'X', 'FontName', 'Helvetica', 'FontWeight', 'bold', ...
      'FontSize', 16 );

    ylabel ( 'Y', 'FontName', 'Helvetica', 'FontWeight', 'bold', ...
      'FontSize', 16, 'Rotation', 0 );

    title ( u_filename, 'FontName', 'Helvetica', 'FontWeight', ...
      'bold', 'FontSize', 16 );
%
%  Here's where we take a snapshot of the current image, and save it to 
%  a PNG file.  Doing this was surprisingly complicated, and the help
%  system was not very clear.  Surely there's a more straightforward way!
%
    F = getframe ( );
    [ XX, map ] = frame2im ( F );
    imwrite ( XX, png_filename, 'PNG' );
    frame_num = frame_num + 1;
%
%  Prepare for next iteration.
%
    u_filename = file_name_inc ( u_filename );

    if ( ~ file_exist ( u_filename ) )
      break
    end
    
    png_filename = file_name_inc ( png_filename );

  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Processed %d frames.\n', frame_num );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'contour_sequence4():\n' );
  fprintf ( 1, '  Normal end of execution.\n' );

  return
end
function truefalse = ch_is_digit ( c )

%*****************************************************************************80
%
%% ch_is_digit() returns TRUE if the character C is a digit.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    11 December 2003
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    character C, a character.
%
%  Output:
%
%    integer TRUEFALSE, is TRUE (1) if C is a digit, FALSE (0) otherwise.
%
  TRUE = 1;
  FALSE = 0;

  if ( '0' <= c && c <= '9' )
    truefalse = TRUE;
  else
    truefalse = FALSE;
  end

  return
end
function c = digit_inc ( c )

%*****************************************************************************80
%
%% digit_inc() increments a digit.
%
%  Discussion:
%
%    0 goes to 1, 1 goes to 2 and so on, but 9 goes back to 0.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    14 June 2005
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    character C, a character.
%
%  Output:
%
%    character C, the incremented character.
%
  if ( '0' <= c && c < '9' )
    c = char ( 1 + double ( c ) );
  elseif ( c == '9' )
    c = '0';
  end

  return
end
function value = file_exist ( file_name )

%*****************************************************************************80
%
%% file_exist() reports whether a file exists.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    29 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    character FILE_NAME, the name of the file.
%
%  Output:
%
%    logical FILE_EXIST, is TRUE if the file exists.
%
  fid = fopen ( file_name );

  if ( fid == -1 ) 
    value = 0;
  else
    fclose ( fid );
    value = 1;
  end

  return
end
function file_name_new = file_name_ext_swap ( file_name, ext )

%*****************************************************************************80
%
%% file_name_ext_swap() replaces the current "extension" of a file name.
%
%  Discussion:
%
%    The "extension" of a filename is the string of characters
%    that appears after the LAST period in the name.  A file
%    with no period, or with a period as the last character
%    in the name, has a "null" extension.
%
%  Example:
%
%          Input           Output
%    ================     =============
%    FILE_NAME    EXT     FILE_NAME_NEW
%    
%    bob.for      obj     bob.obj
%    bob.bob.bob  txt     bob.bob.txt
%    bob          yak     bob.yak
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    15 August 2005
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    character FILE_NAME(*), a file name.
%    On the extension of the file has been changed.
%
%    character EXT(*), the extension to be used on the output
%    copy of FILE_NAME, replacing the current extension if any.
%
%  Output:
%
%    character FILE_NAME_NEW(*), a copy of the input file name,
%    with the new extension.
%
  file_name_len = length ( file_name );

  ext_len = length ( ext );

  period = file_name_len + 1;

  for i = file_name_len : -1 : 1
    if ( file_name(i:i) == '.' )
      period = i;
      break
    end
  end

  file_name_new(1:period-1) = file_name(1:period-1);
  file_name_new(period) = '.';
  file_name_new(period+1:period+ext_len) = ext(1:ext_len);

  return
end
function file_name = file_name_inc ( file_name )

%*****************************************************************************80
%
%% file_name_inc() generates the next filename in a series.
%
%  Discussion:
%
%    It is assumed that the digits in the name, whether scattered or
%    connected, represent a number that is to be increased by 1 on
%    each call.  If this number is all 9's on the output number
%    is all 0's.  Non-numeric letters of the name are unaffected..
%
%    If the name is empty, then the routine stops.
%
%    If the name contains no digits, the empty string is returned.
%
%  Example:
%
%      Input            Output
%      -----            ------
%      'a7to11.txt'     'a7to12.txt'  (typical case.  Last digit incremented)
%      'a7to99.txt'     'a8to00.txt'  (last digit incremented, with carry.)
%      'a9to99.txt'     'a0to00.txt'  (wrap around)
%      'cat.txt'        ' '           (no digits in input name.)
%      ' '              STOP!         (error.)
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    14 September 2005
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    string FILE_NAME, the string to be incremented.
%
%  Output:
%
%    string FILE_NAME, the incremented string.
%
  lens = length ( file_name );

  if ( lens <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_NAME_INC - Fatal error!\n' );
    fprintf ( 1, '  The input filename is empty.\n' );
    error ( 'FILE_NAME_INC - Fatal error!' );
  end

  change = 0;

  for i = lens : -1 : 1

    c = file_name(i);

    if ( '0' <= c && c <= '8' )

      change = change + 1;

      c = c + 1;
      
      file_name(i) = c;

      return

    elseif ( c == '9' )

      change = change + 1;

      c = '0';
      
      file_name(i) = c;

    end

  end

  if ( change == 0 )
    file_name = ' ';
  end

  return
end
function len = s_len_trim ( s )

%*****************************************************************************80
%
%% s_len_trim() returns the length of a character string to the last nonblank.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    14 June 2003
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    string S, the string to be measured.
%
%  Output:
%
%    integer LEN, the length of the string up to the last nonblank.
%
  len = length ( s );

  while ( 0 < len )
    if ( s(len) ~= ' ' )
      return
    end
    len = len - 1;
  end

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% timestamp() prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end

