function blocks_out = ring_gen(ring,blocks,hdr)
%USEAGE: BLOCKS = ring_gen(RING,BLOCKS,HDR);
%
%INPUT ARGUMENTS:
%
%RING
%  Structure of ring parameters. Fields include:
%      FIELD       DESCRIPTION
%      filename    Ring-parameter filename (overwritten)
%
%      r_min       minimum radial extent of bounding volume.
%
%      r_max       maximum radial extent of bounding volume.
%
%      z_min       minimum axial position of bounding volume.
%
%      z_max       maximum axial position of bounding volume.
%
%RING
%
%BLOCKS    
%  Array of structures giving number and arrangement for each 
%  type of block. Fields of the I-th block type are stored in 
%  BLOCKS(I).FIELD, where FIELD is:
%      FIELD       DESCRIPTION
%      filename    Name of block parameter file
%
%      r_min       Inner radius at which to distribute blocks
%
%      count       Number of this block type in ring
%
%      azimuth     Azmuthal position of one or all blocks with
%                  respect to block reference point (given in 
%                  block param file).  If only one angle is given
%                  then this value is take as azmuthal position of
%                  first block.  In this case, the rest of the 
%                  (count-1) blocks are uniformly distributed about 
%                  this position.  An array of azmuthal positions
%                  for all blocks is returned in this field in
%                  either case.
%      z_pos       Axial position blocks (one value for all blocks).
%
%      tilt        Transaxial orientation of blocks from block 
%                  reference point.  A scalar value indicates that 
%                  all blocks have the same tilt.  A vector must
%                  used to provide different tilt for each block.
%
%HDR
 %  Optional structure giving information for file header. The date 
%  and ring.filename are automatically included (no user input needed).
%  User input fields include:
%      FIELD       DESCRIPTION
%      author      string giving name of author
%
%      comments    list of strings giving comments (1 item per line) 
%
%OUTPUTS
%
%BLOCKS
%  Updated structures of blocks including array of azimuths and tilts
%
%William Hunter, 2008-06-01

Ntype = numel(blocks);
Nblk = 0;
for n = 1:Ntype
    cnt = blocks(n).count;
    
    Nblk = Nblk + cnt;
    
    az = blocks(n).azimuth;
    len = numel(az);
    if len == 1
        blocks(n).azimuth = az + (0:(cnt-1))*(360/cnt);
    elseif len ~= cnt
        error(['blocks(',num2str(n),').azimuth is incorrectly sized']);
    end
    
    yaw = blocks(n).tilt;
    len = numel(yaw);
    if len == 1
        blocks(n).tilt = repmat(yaw,cnt,1);
    elseif len ~= cnt
        error(['blocks(',num2str(n),').yaw is incorrectly sized']);
    end
end

fid = fopen(ring.filename,'wt');

%Write Header
txt{1} = ['#  Ring parameter file: ',ring.filename];
if nargin>2
    if isfield(hdr,'author')
        txt{end+1} = ['#  Author/Owner:        ',hdr.author];
    end
    if isfield(hdr,'comments')
        if iscell(hdr.comments)
            txt{end+1} = ['#  Comments:            ',hdr.comments{1}];
            for i = 2:numel(hdr.comments)
                txt{end+1} = ['#                       ',hdr.comments{i}];
            end
        elseif ischar(hdr.comments)
            txt{end+1} = ['#  Comments:            ',hdr.comments];
        else
            error('hdr.comments is not a string or list of strings');
        end
    end
end

max_len = 2;
for i = 1:numel(txt)
    max_len = max(max_len,length(txt{i}));
end

fprintf(fid,[repmat('#',1,max_len),'\n#\n']);
for i = 1:numel(txt), fprintf(fid,[txt{i},'\n']); end
fprintf(fid,['#\n',repmat('#',1,max_len),'\n']);
fprintf(fid,'\n');


%Write ring bounding volume
fprintf(fid,'# RING OUTER DIMENSIONS\n');
fprintf(fid,'# Provides the outer dimensions of the ring: all the blocks must fall entirely\n');
fprintf(fid,'# within these boundaries.  The ring is bounded with a maximum and minimum\n');
fprintf(fid,'# z value axially and by elliptical cylinders transaxially.  These bounds are not\n');
fprintf(fid,'# in tomograph coordinates: the ring can shifted up or down axially or rotated\n');
fprintf(fid,'# transaxially when placing it in the tomograph.\n');
fprintf(fid,'REAL	ring_x_inner_radius     =   %0.14f\n',ring.r_min);
fprintf(fid,'REAL	ring_x_outer_radius     =   %0.14f\n',ring.r_max);
fprintf(fid,'REAL	ring_y_inner_radius     =   %0.14f\n',ring.r_min);
fprintf(fid,'REAL	ring_y_outer_radius     =   %0.14f\n',ring.r_max);
fprintf(fid,'REAL	ring_z_minimum          =   %0.14f\n',ring.z_min);
fprintf(fid,'REAL	ring_z_maximum          =   %0.14f\n',ring.z_max);
fprintf(fid,'\n');


%Write Number of Blocks
fprintf(fid,'NUM_ELEMENTS_IN_LIST   ring_num_blocks_in_ring  = %d\n',Nblk);
fprintf(fid,'\n');


%Write blocks
blk_num = 0;
Nblk_el = 5;
for n = 1:Ntype
    for i = 1:blocks(n).count
        fprintf(fid,'# Block    %d\n',blk_num);
        fprintf(fid,'NUM_ELEMENTS_IN_LIST   ring_block_description_list  = %d\n',Nblk_el);
        fprintf(fid,'STR      ring_block_parameter_file                  = %s\n',blocks(n).filename);
        fprintf(fid,'REAL     ring_block_radial_position                 = %0.14f\n',blocks(n).r_min);
        fprintf(fid,'REAL     ring_block_angular_position                = %0.14f\n',blocks(n).azimuth(i));
        fprintf(fid,'REAL     ring_block_z_position                      = %0.14f\n',blocks(n).z_pos);
        fprintf(fid,'REAL     ring_block_transaxial_orientation          = %0.14f\n',blocks(n).tilt(i));
        fprintf(fid,'\n');
        blk_num = blk_num + 1;
    end
end

fclose(fid);

if nargout>0; blocks_out = blocks; end