=pod

=head1 NAME



B<FunTableRowPut - put Funtools rows>



=head1 SYNOPSIS





int FunTableRowPut(Fun fun, void *rows, int nev, int idx, char *plist)





=head1 DESCRIPTION



The B<FunTableRowPut()> routine writes rows to a FITS binary
table, taking its input from an array of user structs that contain
column values selected by a previous call to 
FunColumnSelect().  Selected
column values are automatically converted from native data format to
FITS data format as necessary.


The first argument is the Fun handle associated with this row data.
The second B<rows> argument is the array of user structs to
output. The third B<nrow> argument specifies the number number of
rows to write.  The routine will write B<nrow> records, starting
from the location specified by B<rows>.


The fourth B<idx> argument is the index of the first raw input
row to write, in the case where rows from the user buffer are
being merged with their raw input row counterparts (see below). Note
that this B<idx> value is has nothing to do with the
row buffer specified in argument 1.  It merely matches the row
being written with its corresponding (hidden) raw row.  Thus, if you
read a number of rows, process them, and then write them out all at
once starting from the first user row, the value of B<idx>
should be 0:

  Ev ebuf, ev;
  /* get rows -- let routine allocate the row array */
  while( (ebuf = (Ev)FunTableRowGet(fun, NULL, MAXROW, NULL, &got)) ){
    /* process all rows */
    for(i=0; i<got; i++){
      /* point to the i'th row */
      ev = ebuf+i;
      ...
    }
    /* write out this batch of rows, starting with the first */
    FunTableRowPut(fun2, (char *)ebuf, got, 0, NULL);
    /* free row data */
    if( ebuf ) free(ebuf);
  }



On the other hand, if you write out the rows one at a time (possibly
skipping rows), then, when writing the i'th row from the input
array of rows, set B<idx> to the value of i:

  Ev ebuf, ev;
  /* get rows -- let routine allocate the row array */
  while( (ebuf = (Ev)FunTableRowGet(fun, NULL, MAXROW, NULL, &got)) ){
    /* process all rows */
    for(i=0; i<got; i++){
      /* point to the i'th row */
      ev = ebuf+i;
      ...
      /* write out the current (i.e., i'th) row */
      FunTableRowPut(fun2, (char *)ev, 1, i, NULL);
    }
    /* free row data */
    if( ebuf ) free(ebuf);
  }



The final argument is a param list string that is not currently used.
The routine returns the number of rows output.  This should be equal
to the value passed in the third nrow</B argument.


When FunTableRowPut() is first
called for a given binary table, Funtools checks to see of the primary
header has already been written (either by writing a previous row
table or by writing an image.) If not, a dummy primary header is
written to the file specifying that an extension should be expected.
After this, a binary table header is automatically written containing
information about the columns that will populate this table.  In
addition, if a 
Funtools reference handle
was specified when this table was opened, the parameters from this
Funtools reference handle
are merged into the new binary table header.


In a typical Funtools row loop, you read rows using 
FunTableRowGet()() and write
rows using FunTableRowPut(). The columns written by
FunTableRowPut()() are those defined as writable by a previous call to
FunColumnSelect().  If
that call to FunColumnSelect also specified
B<merge=[update|replace|append]>, then the entire corresponding
raw input row record will be merged with the output row according
to the B<merge> specification (see 
FunColumnSelect() above).


A call to write rows can either be done once, after all rows in
the input batch have been processed, or it can be done (slightly less
efficiently) one row at a time (or anything in between). We do
recommend that you write all rows associated with a given batch of
input rows before reading new rows.  This is B<required> if
you are merging the output rows with the raw input rows (since
the raw rows are destroyed with each successive call to get new rows).

For example:

  Ev buf, ev;
  ...
  /* get rows -- let routine allocate the row array */
  while( (buf = (Ev)FunTableRowGet(fun, NULL, MAXROW, NULL, &got)) ){
    /* point to the i'th row */
    ev = buf + i;
    .... process
  }
  /* write out this batch of rows */
  FunTableRowPut(fun2, buf, got, 0, NULL);
  /* free row data */
  if( buf ) free(buf);
  }


or


  Ev buf, ev;
  ...
  /* get rows -- let routine allocate the row array */
  while( (buf = (Ev)FunTableRowGet(fun, NULL, MAXROW, NULL, &got)) ){
    /* process all rows */
    for(i=0; i<got; i++){
      /* point to the i'th row */
      ev = buf + i;
      ... process
      /* write out this batch of rows with the new column */
      if( dowrite )
        FunTableRowPut(fun2, buf, 1, i, NULL);
    }
    /* free row data */
    if( buf ) free(buf);
  }



Note that the difference between these calls is that the first one
outputs B<got> rows all at once and therefore passes
B<idx=0> in argument four, so that merging starts at the first raw
input row.  In the second case, a check it made on each row to see
if it needs to be output.  If so, the value of B<idx> is passed as
the value of the B<i> variable which points to the current row
being processed in the batch of input rows.


As shown above, successive calls to 
FunTableRowPut() will write
rows sequentially. When you are finished writing all rows in a
table, you should call 
FunFlush() to write out the FITS
binary table padding. However, this is not necessary if you
subsequently call FunClose() without doing any other I/O to the FITS
file.


Note that FunTableRowPut() also can be called as FunEventsPut(), for
backward compatibility.




=head1 SEE ALSO



See funtools(n) for a list of Funtools help pages


=cut
