diff options
Diffstat (limited to 'man/man1/funcalc.1')
-rw-r--r-- | man/man1/funcalc.1 | 622 |
1 files changed, 622 insertions, 0 deletions
diff --git a/man/man1/funcalc.1 b/man/man1/funcalc.1 new file mode 100644 index 0000000..b864865 --- /dev/null +++ b/man/man1/funcalc.1 @@ -0,0 +1,622 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "funcalc 1" +.TH funcalc 1 "April 14, 2011" "version 1.4.5" "SAORD Documentation" +.SH "NAME" +funcalc \- Funtools calculator (for binary tables) +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +\&\fBfuncalc\fR [\-n] [\-a argstr] [\-e expr] [\-f file] [\-l link] [\-p prog] <iname> [oname [columns]] +.SH "OPTIONS" +.IX Header "OPTIONS" +.Vb 7 +\& \-a argstr # user arguments to pass to the compiled program +\& \-e expr # funcalc expression +\& \-f file # file containing funcalc expression +\& \-l libs # libs to add to link command +\& \-n # output generated code instead of compiling and executing +\& \-p prog # generate named program, no execution +\& \-u # die if any variable is undeclared (don't auto-declare) +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +\&\fBfuncalc\fR is a calculator program that allows arbitrary +expressions to be constructed, compiled, and executed on columns in a +Funtools table (\s-1FITS\s0 binary table or raw event file). It works by +integrating user-supplied expression(s) into a template C program, +then compiling and executing the program. \fBfuncalc\fR expressions +are C statements, although some important simplifications (such +as automatic declaration of variables) are supported. +.PP +\&\fBfuncalc\fR expressions can be specified in three ways: on the +command line using the \fB\-e [expression]\fR switch, in a file using +the \fB\-f [file]\fR switch, or from stdin (if neither \fB\-e\fR nor +\&\fB\-f\fR is specified). Of course a file containing \fBfuncalc\fR +expressions can be read from stdin. +.PP +Each invocation of \fBfuncalc\fR requires an input Funtools table +file to be specified as the first command line argument. The output +Funtools table file is the second optional argument. It is needed only +if an output \s-1FITS\s0 file is being created (i.e., in cases where the +\&\fBfuncalc\fR expression only prints values, no output file is +needed). If input and output file are both specified, a third optional +argument can specify the list of columns to activate (using +\&\fIFunColumnActivate()\fR). Note +that \fBfuncalc\fR determines whether or not to generate code for +writing an output file based on the presence or absence of an +output file argument. +.PP +A \fBfuncalc\fR expression executes on each row of a table and +consists of one or more C statements that operate on the columns of +that row (possibly using temporary variables). Within an expression, +reference is made to a column of the \fBcurrent\fR row using the C +struct syntax \fBcur\-\fR[colname]>, e.g. cur\->x, cur\->pha, etc. +Local scalar variables can be defined using C declarations at very the +beginning of the expression, or else they can be defined automatically +by \fBfuncalc\fR (to be of type double). Thus, for example, a swap of +columns x and y in a table can be performed using either of the +following equivalent \fBfuncalc\fR expressions: +.PP +.Vb 4 +\& double temp; +\& temp = cur->x; +\& cur->x = cur->y; +\& cur->y = temp; +.Ve +.PP +or: +.PP +.Vb 3 +\& temp = cur->x; +\& cur->x = cur->y; +\& cur->y = temp; +.Ve +.PP +When this expression is executed using a command such as: +.PP +.Vb 1 +\& funcalc \-f swap.expr itest.ev otest.ev +.Ve +.PP +the resulting file will have values of the x and y columns swapped. +.PP +By default, the data type of the variable for a column is the same as +the data type of the column as stored in the file. This can be changed +by appending \*(L":[dtype]\*(R" to the first reference to that column. In the +example above, to force x and y to be output as doubles, specify the +type 'D' explicitly: +.PP +.Vb 3 +\& temp = cur->x:D; +\& cur->x = cur->y:D; +\& cur->y = temp; +.Ve +.PP +Data type specifiers follow standard \s-1FITS\s0 table syntax for defining +columns using \s-1TFORM:\s0 +.IP "\(bu" 4 +A: \s-1ASCII\s0 characters +.IP "\(bu" 4 +B: unsigned 8-bit char +.IP "\(bu" 4 +I: signed 16-bit int +.IP "\(bu" 4 +U: unsigned 16-bit int (not standard \s-1FITS\s0) +.IP "\(bu" 4 +J: signed 32-bit int +.IP "\(bu" 4 +V: unsigned 32-bit int (not standard \s-1FITS\s0) +.IP "\(bu" 4 +E: 32-bit float +.IP "\(bu" 4 +D: 64-bit float +.IP "\(bu" 4 +X: bits (treated as an array of chars) +.PP +Note that only the first reference to a column should contain the +explicit data type specifier. +.PP +Of course, it is important to handle the data type of the columns +correctly. One of the most frequent cause of error in \fBfuncalc\fR +programming is the implicit use of the wrong data type for a column in +expression. For example, the calculation: +.PP +.Vb 1 +\& dx = (cur->x - cur->y)/(cur->x + cur->y); +.Ve +.PP +usually needs to be performed using floating point arithmetic. In +cases where the x and y columns are integers, this can be done by +reading the columns as doubles using an explicit type specification: +.PP +.Vb 1 +\& dx = (cur->x:D - cur->y:D)/(cur->x + cur->y); +.Ve +.PP +Alternatively, it can be done using C type-casting in the expression: +.PP +.Vb 1 +\& dx = ((double)cur->x - (double)cur->y)/((double)cur->x + (double)cur->y); +.Ve +.PP +In addition to accessing columns in the current row, reference also +can be made to the \fBprevious\fR row using \fBprev\-\fR[colname]>, +and to the \fBnext\fR row using \fBnext\-\fR[colname]>. Note that if +\&\fBprev\-\fR[colname]> is specified in the \fBfuncalc\fR +expression, the very first row is not processed. If +\&\fBnext\-\fR[colname]> is specified in the \fBfuncalc\fR +expression, the very last row is not processed. In this way, +\&\fBprev\fR and \fBnext\fR are guaranteed always to point to valid +rows. For example, to print out the values of the current x column +and the previous y column, use the C fprintf function in a +\&\fBfuncalc\fR expression: +.PP +.Vb 1 +\& fprintf(stdout, "%d %d\en", cur->x, prev->y); +.Ve +.PP +New columns can be specified using the same \fBcur\-\fR[colname]> +syntax by appending the column type (and optional tlmin/tlmax/binsiz +specifiers), separated by colons. For example, cur\->avg:D will define +a new column of type double. Type specifiers are the same those +used above to specify new data types for existing columns. +.PP +For example, to create and output a new column that is the average value of the +x and y columns, a new \*(L"avg\*(R" column can be defined: +.PP +.Vb 1 +\& cur->avg:D = (cur->x + cur->y)/2.0 +.Ve +.PP +Note that the final ';' is not required for single-line expressions. +.PP +As with \s-1FITS\s0 \s-1TFORM\s0 data type specification, the column data type +specifier can be preceded by a numeric count to define an array, e.g., +\&\*(L"10I\*(R" means a vector of 10 short ints, \*(L"2E\*(R" means two single precision +floats, etc. A new column only needs to be defined once in a +\&\fBfuncalc\fR expression, after which it can be used without +re-specifying the type. This includes reference to elements of a +column array: +.PP +.Vb 2 +\& cur->avg[0]:2D = (cur->x + cur->y)/2.0; +\& cur->avg[1] = (cur->x - cur->y)/2.0; +.Ve +.PP +The 'X' (bits) data type is treated as a char array of dimension +(numeric_count/8), i.e., 16X is processed as a 2\-byte char array. Each +8-bit array element is accessed separately: +.PP +.Vb 2 +\& cur->stat[0]:16X = 1; +\& cur->stat[1] = 2; +.Ve +.PP +Here, a 16-bit column is created with the \s-1MSB\s0 is set to 1 and the \s-1LSB\s0 set to 2. +.PP +By default, all processed rows are written to the specified output +file. If you want to skip writing certain rows, simply execute the C +\&\*(L"continue\*(R" statement at the end of the \fBfuncalc\fR expression, +since the writing of the row is performed immediately after the +expression is executed. For example, to skip writing rows whose +average is the same as the current x value: +.PP +.Vb 4 +\& cur->avg[0]:2D = (cur->x + cur->y)/2.0; +\& cur->avg[1] = (cur->x - cur->y)/2.0; +\& if( cur->avg[0] == cur->x ) +\& continue; +.Ve +.PP +If no output file argument is specified on the \fBfuncalc\fR command +line, no output file is opened and no rows are written. This is useful +in expressions that simply print output results instead of generating +a new file: +.PP +.Vb 5 +\& fpv = (cur->av3:D-cur->av1:D)/(cur->av1+cur->av2:D+cur->av3); +\& fbv = cur->av2/(cur->av1+cur->av2+cur->av3); +\& fpu = ((double)cur->au3-cur->au1)/((double)cur->au1+cur->au2+cur->au3); +\& fbu = cur->au2/(double)(cur->au1+cur->au2+cur->au3); +\& fprintf(stdout, "%f\et%f\et%f\et%f\en", fpv, fbv, fpu, fbu); +.Ve +.PP +In the above example, we use both explicit type specification +(for \*(L"av\*(R" columns) and type casting (for \*(L"au\*(R" columns) to ensure that +all operations are performed in double precision. +.PP +When an output file is specified, the selected input table is +processed and output rows are copied to the output file. Note that +the output file can be specified as \*(L"stdout\*(R" in order to write the +output rows to the standard output. If the output file argument is +passed, an optional third argument also can be passed to specify which +columns to process. +.PP +In a \s-1FITS\s0 binary table, it sometimes is desirable to copy all of the +other \s-1FITS\s0 extensions to the output file as well. This can be done by +appending a '+' sign to the name of the extension in the input file +name. See \fBfuntable\fR for a related example. +.PP +\&\fBfuncalc\fR works by integrating the user-specified expression +into a template C program called tabcalc.c. +The completed program then is compiled and executed. Variable +declarations that begin the \fBfuncalc\fR expression are placed in +the local declaration section of the template main program. All other +lines are placed in the template main program's inner processing +loop. Other details of program generation are handled +automatically. For example, column specifiers are analyzed to build a +C struct for processing rows, which is passed to +\&\fIFunColumnSelect()\fR and used +in \fIFunTableRowGet()\fR. If +an unknown variable is used in the expression, resulting in a +compilation error, the program build is retried after defining the +unknown variable to be of type double. +.PP +Normally, \fBfuncalc\fR expression code is added to +\&\fBfuncalc\fR row processing loop. It is possible to add code +to other parts of the program by placing this code inside +special directives of the form: +.PP +.Vb 3 +\& [directive name] +\& ... code goes here ... +\& end +.Ve +.PP +The directives are: +.IP "\(bu" 4 +\&\fBglobal\fR add code and declarations in global space, before the main routine. +.IP "\(bu" 4 +\&\fBlocal\fR add declarations (and code) just after the local declarations in +main +.IP "\(bu" 4 +\&\fBbefore\fR add code just before entering the main row processing loop +.IP "\(bu" 4 +\&\fBafter\fR add code just after exiting the main row processing loop +.PP +Thus, the following \fBfuncalc\fR expression will declare global +variables and make subroutine calls just before and just after the +main processing loop: +.PP +.Vb 16 +\& global +\& double v1, v2; +\& double init(void); +\& double finish(double v); +\& end +\& before +\& v1 = init(); +\& end +\& ... process rows, with calculations using v1 ... +\& after +\& v2 = finish(v1); +\& if( v2 < 0.0 ){ +\& fprintf(stderr, "processing failed %g -> %g\en", v1, v2); +\& exit(1); +\& } +\& end +.Ve +.PP +Routines such as \fIinit()\fR and \fIfinish()\fR above are passed to the generated +program for linking using the \fB\-l [link directives ...]\fR +switch. The string specified by this switch will be added to the link +line used to build the program (before the funtools library). For +example, assuming that \fIinit()\fR and \fIfinish()\fR are in the library +libmysubs.a in the /opt/special/lib directory, use: +.PP +.Vb 1 +\& funcalc \-l "\-L/opt/special/lib \-lmysubs" ... +.Ve +.PP +User arguments can be passed to a compiled funcalc program using a string +argument to the \*(L"\-a\*(R" switch. The string should contain all of the +user arguments. For example, to pass the integers 1 and 2, use: +.PP +.Vb 1 +\& funcalc \-a "1 2" ... +.Ve +.PP +The arguments are stored in an internal array and are accessed as +strings via the \s-1ARGV\s0(n) macro. For example, consider the following +expression: +.PP +.Vb 3 +\& local +\& int pmin, pmax; +\& end +.Ve +.PP +.Vb 4 +\& before +\& pmin=atoi(ARGV(0)); +\& pmax=atoi(ARGV(1)); +\& end +.Ve +.PP +.Vb 2 +\& if( (cur->pha >= pmin) && (cur->pha <= pmax) ) +\& fprintf(stderr, "%d %d %d\en", cur->x, cur->y, cur->pha); +.Ve +.PP +This expression will print out x, y, and pha values for all rows in which +the pha value is between the two user-input values: +.PP +.Vb 6 +\& funcalc \-a '1 12' \-f foo snr.ev'[cir 512 512 .1]' +\& 512 512 6 +\& 512 512 8 +\& 512 512 5 +\& 512 512 5 +\& 512 512 8 +.Ve +.PP +.Vb 4 +\& funcalc \-a '5 6' \-f foo snr.ev'[cir 512 512 .1]' +\& 512 512 6 +\& 512 512 5 +\& 512 512 5 +.Ve +.PP +Note that it is the user's responsibility to ensure that the correct +number of arguments are passed. The \s-1ARGV\s0(n) macro returns a \s-1NULL\s0 if a +requested argument is outside the limits of the actual number of args, +usually resulting in a \s-1SEGV\s0 if processed blindly. To check the +argument count, use the \s-1ARGC\s0 macro: +.PP +.Vb 4 +\& local +\& long int seed=1; +\& double limit=0.8; +\& end +.Ve +.PP +.Vb 5 +\& before +\& if( ARGC >= 1 ) seed = atol(ARGV(0)); +\& if( ARGC >= 2 ) limit = atof(ARGV(1)); +\& srand48(seed); +\& end +.Ve +.PP +.Vb 1 +\& if ( drand48() > limit ) continue; +.Ve +.PP +The macro \s-1WRITE_ROW\s0 expands to the \fIFunTableRowPut()\fR call that writes +the current row. It can be used to write the row more than once. In +addition, the macro \s-1NROW\s0 expands to the row number currently being +processed. Use of these two macros is shown in the following example: +.PP +.Vb 7 +\& if( cur->pha:I == cur->pi:I ) continue; +\& a = cur->pha; +\& cur->pha = cur->pi; +\& cur->pi = a; +\& cur->AVG:E = (cur->pha+cur->pi)/2.0; +\& cur->NR:I = NROW; +\& if( NROW < 10 ) WRITE_ROW; +.Ve +.PP +If the \fB\-p [prog]\fR switch is specified, the expression is not +executed. Rather, the generated executable is saved with the specified +program name for later use. +.PP +If the \fB\-n\fR switch is specified, the expression is not +executed. Rather, the generated code is written to stdout. This is +especially useful if you want to generate a skeleton file and add your +own code, or if you need to check compilation errors. Note that the +comment at the start of the output gives the compiler command needed +to build the program on that platform. (The command can change from +platform to platform because of the use of different libraries, +compiler switches, etc.) +.PP +As mentioned previously, \fBfuncalc\fR will declare a scalar +variable automatically (as a double) if that variable has been used +but not declared. This facility is implemented using a sed script +named funcalc.sed, which processes the +compiler output to sense an undeclared variable error. This script +has been seeded with the appropriate error information for gcc, and for +cc on Solaris, DecAlpha, and \s-1SGI\s0 platforms. If you find that automatic +declaration of scalars is not working on your platform, check this sed +script; it might be necessary to add to or edit some of the error +messages it senses. +.PP +In order to keep the lexical analysis of \fBfuncalc\fR expressions +(reasonably) simple, we chose to accept some limitations on how +accurately C comments, spaces, and new-lines are placed in the +generated program. In particular, comments associated with local +variables declared at the beginning of an expression (i.e., not in a +\&\fBlocal...end\fR block) will usually end up in the inner loop, not +with the local declarations: +.PP +.Vb 8 +\& /* this comment will end up in the wrong place (i.e, inner loop) */ +\& double a; /* also in wrong place */ +\& /* this will be in the the right place (inner loop) */ +\& if( cur->x:D == cur->y:D ) continue; /* also in right place */ +\& a = cur->x; +\& cur->x = cur->y; +\& cur->y = a; +\& cur->avg:E = (cur->x+cur->y)/2.0; +.Ve +.PP +Similarly, spaces and new-lines sometimes are omitted or added in a +seemingly arbitrary manner. Of course, none of these stylistic +blemishes affect the correctness of the generated code. +.PP +Because \fBfuncalc\fR must analyze the user expression using the data +file(s) passed on the command line, the input file(s) must be opened +and read twice: once during program generation and once during +execution. As a result, it is not possible to use stdin for the +input file: \fBfuncalc\fR cannot be used as a filter. We will +consider removing this restriction at a later time. +.PP +Along with C comments, \fBfuncalc\fR expressions can have one-line +internal comments that are not passed on to the generated C +program. These internal comment start with the \fB#\fR character and +continue up to the new\-line: +.PP +.Vb 7 +\& double a; # this is not passed to the generated C file +\& # nor is this +\& a = cur->x; +\& cur->x = cur->y; +\& cur->y = a; +\& /* this comment is passed to the C file */ +\& cur->avg:E = (cur->x+cur->y)/2.0; +.Ve +.PP +As previously mentioned, input columns normally are identified by +their being used within the inner event loop. There are rare cases +where you might want to read a column and process it outside the main +loop. For example, qsort might use a column in its sort comparison +routine that is not processed inside the inner loop (and therefore not +implicitly specified as a column to be read). To ensure that such a +column is read by the event loop, use the \fBexplicit\fR keyword. +The arguments to this keyword specify columns that should be read into +the input record structure even though they are not mentioned in the +inner loop. For example: +.PP +.Vb 1 +\& explicit pi pha +.Ve +.PP +will ensure that the pi and pha columns are read for each row, +even if they are not processed in the inner event loop. The \fBexplicit\fR +statement can be placed anywhere. +.PP +Finally, note that \fBfuncalc\fR currently works on expressions +involving \s-1FITS\s0 binary tables and raw event files. We will consider +adding support for image expressions at a later point, if there is +demand for such support from the community. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +See funtools(7) for a list of Funtools help pages |