parent
f43dae9f53
commit
200bc18074
|
@ -0,0 +1,3 @@
|
|||
Nicolas Devillard ndevilla@eso.org
|
||||
Yves Jung yjung@eso.org
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
Installing qfits as an ANSI C library
|
||||
-------------------------------------
|
||||
|
||||
% ./configure
|
||||
% make
|
||||
|
||||
That should do it. You should now have a library called
|
||||
libqfits.a in the lib/ directory, and the include files
|
||||
you need are in the include/ directory.
|
||||
|
||||
To review possible configure options, type:
|
||||
% configure --help
|
||||
|
||||
To install this library system-wide, use:
|
||||
% make install
|
||||
|
||||
This will install the library in /opt/qfits. To change the
|
||||
destination, use the --prefix option from configure.
|
||||
Example: to install under /usr/local/qfits you would do:
|
||||
% configure --prefix=/usr/local/qfits
|
||||
|
||||
If you want to perform basic tests, use:
|
||||
% make tests
|
||||
|
||||
|
||||
Using qfits from C++
|
||||
--------------------
|
||||
|
||||
Compile the C library and link your C++ program against
|
||||
libqfits.a. This will avoid a number of issues with your
|
||||
C++ compiler trying to compile a C library.
|
||||
|
||||
|
||||
Installing qfits as a Python module
|
||||
-----------------------------------
|
||||
|
||||
See python/README in this directory.
|
||||
|
||||
Using qfits from other languages
|
||||
--------------------------------
|
||||
|
||||
This used to be offered through a SWIG interface file, but
|
||||
is not supported any more.
|
||||
|
||||
|
||||
Fri Nov 30 11:36:29 CET 2001
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
Copyright (c) 1995-2001, European Southern Observatory
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,102 @@
|
|||
#
|
||||
# qfits Makefile
|
||||
#
|
||||
|
||||
include config.make
|
||||
|
||||
AR = ar
|
||||
ARFLAGS = rc
|
||||
RM = rm -f
|
||||
CP = cp -f
|
||||
|
||||
|
||||
# Implicit rules
|
||||
|
||||
SUFFIXES = .o .c .h .a .so .sl
|
||||
|
||||
COMPILE.c=$(CC) $(CFLAGS) $(FTRACE) -Iinclude $(RELOC) -c
|
||||
.c.o:
|
||||
@(echo "compiling $< ...")
|
||||
@($(COMPILE.c) -o $@ $<)
|
||||
|
||||
|
||||
SRCS = src/byteswap.c \
|
||||
src/cache.c \
|
||||
src/expkey.c \
|
||||
src/fits_h.c \
|
||||
src/fits_md5.c \
|
||||
src/fits_p.c \
|
||||
src/fits_rw.c \
|
||||
src/md5.c \
|
||||
src/pixio.c \
|
||||
src/ptrace.c \
|
||||
src/qerror.c \
|
||||
src/simple.c \
|
||||
src/t_iso8601.c \
|
||||
src/tfits.c \
|
||||
src/version.c \
|
||||
src/xmemory.c
|
||||
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
|
||||
default: all
|
||||
|
||||
all: $(TARGETS) progs
|
||||
|
||||
static: lib/libqfits.a
|
||||
|
||||
dynamic: lib/libqfits.$(DYNSUF)
|
||||
|
||||
lib/libqfits.a: $(OBJS)
|
||||
@(echo "Building static library...")
|
||||
@($(AR) $(ARFLAGS) lib/libqfits.a $(OBJS))
|
||||
|
||||
lib/libqfits.$(DYNSUF): $(OBJS)
|
||||
@(echo "Building shared library...")
|
||||
@(ld $(SHARED) -o lib/libqfits.$(DYNSUF) $(OBJS))
|
||||
|
||||
install:
|
||||
@(echo "Installing library in " $(prefix))
|
||||
mkdir -p $(prefix)
|
||||
mkdir -p $(prefix)/lib
|
||||
mkdir -p $(prefix)/include
|
||||
mkdir -p $(prefix)/bin
|
||||
$(CP) include/qfits.h $(prefix)/include
|
||||
$(CP) src/xmemory.h $(prefix)/include
|
||||
$(CP) lib/libqfits.a $(prefix)/lib
|
||||
$(CP) bin/* $(prefix)/bin
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS)
|
||||
|
||||
veryclean:
|
||||
$(RM) $(OBJS) lib/libqfits.a lib/libqfits.$(DYNSUF)
|
||||
$(RM) -r build
|
||||
cd test ; $(MAKE) veryclean ; cd ..
|
||||
cd main ; $(MAKE) veryclean ; cd ..
|
||||
cd saft ; $(MAKE) veryclean ; cd ..
|
||||
|
||||
#
|
||||
# Build example and stand-alone programs
|
||||
#
|
||||
|
||||
progs:
|
||||
cd main ; $(MAKE) ; cd ..
|
||||
cd saft ; $(MAKE) ; cd ..
|
||||
|
||||
#
|
||||
# Building qfits as a Python module.
|
||||
#
|
||||
# type:
|
||||
# % python setup.py build
|
||||
# % python setup.py install
|
||||
#
|
||||
|
||||
docs:
|
||||
@(echo "Building HTML documentation...")
|
||||
@(cd doc ; $(MAKE))
|
||||
|
||||
tests:
|
||||
cd test ; $(MAKE)
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
qfits: a quick and simple FITS access library
|
||||
---------------------------------------------
|
||||
|
||||
|
||||
qfits is a stand-alone FITS library aiming at simplicity rather than
|
||||
trying to cover every possible application field in the FITS domain.
|
||||
|
||||
The FITS format is pretty simple, declaring ancillary data in 80-char
|
||||
lines in ASCII format, and storing values in fixed-size, uncompressed
|
||||
format. Data are stored on the disk more or less as they will be in
|
||||
memory (bar some trivial transformations).
|
||||
|
||||
This library tries to cover various needs. It has not been developped
|
||||
from scratch as a library trying to cover the FITS format, but rather
|
||||
built day after day upon request. There are several levels of
|
||||
complexity, depending on whether you only want to retrieve ancillary
|
||||
data from headers, or only read pixels in, or do some true data
|
||||
manipulation or header re-formatting.
|
||||
|
||||
qfits is written in 100% pure ANSI C that should compile on any Unix.
|
||||
qfits has not been compiled or tested on any non-Unix platform. qfits
|
||||
has been shown to work reliably on the following platforms:
|
||||
|
||||
- Solaris
|
||||
- HPUX
|
||||
- AIX
|
||||
- Dec/OSF1 (True64)
|
||||
- Linux
|
||||
- BSD (tested on FreeBSD and Darwin, aka Mac OS X)
|
||||
|
||||
qfits should work fine on all POSIX-compliant Unixes.
|
||||
If you port qfits to any other platform, please let me know.
|
||||
|
||||
You can compile this library with a C++ compiler for inclusion in a C++
|
||||
program, the header files include the usual blurb to allow that without
|
||||
warning from the compiler.
|
||||
|
||||
qfits also exports a limited number of functionalities to
|
||||
retrieve and parse FITS headers under Python. See the INSTALL
|
||||
file to learn how to install qfits as a Python module.
|
||||
|
||||
N. Devillard
|
||||
Tue Mar 20 11:22:30 CET 2001
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Bootstrap script: it tries to compile a simple C script using cc or
|
||||
# gcc and launches it to create config.h and config.make files.
|
||||
#
|
||||
|
||||
echo "configuring qfits..."
|
||||
if (cc -o sysconf sysconf.c) ; then
|
||||
echo "compiled sysconf successfully"
|
||||
elif (gcc -o sysconf sysconf.c) ; then
|
||||
echo "compiled sysconf successfully"
|
||||
else echo "cannot find cc or gcc: aborting" ; exit
|
||||
fi
|
||||
./sysconf $*
|
||||
mv config.h ./src
|
||||
rm -f sysconf
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
H1 { text-align: center; }
|
||||
A.qindex {}
|
||||
A.qindexRef {}
|
||||
A.el { text-decoration: none; font-weight: bold }
|
||||
A.elRef { font-weight: bold }
|
||||
A.code { text-decoration: none; font-weight: normal; color: #4444ee }
|
||||
A.codeRef { font-weight: normal; color: #4444ee }
|
||||
DL.el { margin-left: -1cm }
|
||||
DIV.fragment { width: 100%; border: none; background-color: #eeeeee }
|
||||
DIV.ah { background-color: black; margin-bottom: 3; margin-top: 3 }
|
||||
TD.md { background-color: #f2f2ff }
|
||||
DIV.groupHeader { margin-left: 16; margin-top: 12; margin-bottom: 6; font-weight: bold }
|
||||
DIV.groupText { margin-left: 16; font-style: italic; font-size: smaller }
|
||||
FONT.keyword { color: #008000 }
|
||||
FONT.keywordtype { color: #604020 }
|
||||
FONT.keywordflow { color: #e08000 }
|
||||
FONT.comment { color: #800000 }
|
||||
FONT.preprocessor { color: #806020 }
|
||||
FONT.stringliteral { color: #002080 }
|
||||
FONT.charliteral { color: #008080 }
|
|
@ -0,0 +1,272 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta name="author" content="ndevil@eso.org">
|
||||
<meta name="editor" content="ndevil@eso.org">
|
||||
<meta name="maintainer" content="ndevil@eso.org">
|
||||
<meta name="organisation" content="ESO, DMD">
|
||||
<meta name="keywords" content="eso, FITS format, C library">
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||
<title>qfits 4.0</title>
|
||||
</head>
|
||||
|
||||
<body text="#000000" bgcolor="#ffffff">
|
||||
|
||||
|
||||
|
||||
<!-- Generated by Doxygen 1.2.5 on Wed Jan 23 15:41:02 2002 -->
|
||||
<h1>qfits reference Manual</h1>
|
||||
<p>
|
||||
<h3 align="center">4.0</h3>
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
<a name="welcome"><h2>Introduction</h2></a>
|
||||
|
||||
<p>
|
||||
<b>qfits</b> is a stand-alone written in C to handle interactions with files complying with the FITS format. It is extremely fast and portable over any kind of POSIX-compliant platform.
|
||||
<p>
|
||||
Rather than going through the FITS format specification and trying to implement some support for everything that is described there, this library was built day after day upon request. This guarantees that all the functions you will find in the library have been written for some purpose in the VLT pipeline context, and all of them are used daily in a production environment.
|
||||
<p>
|
||||
Functionalities offered by this library are:
|
||||
<p>
|
||||
<ul>
|
||||
<li>Header queries (get keywords, values).<li>Header manipulation (load/modify/save).<li>Pixel loading/saving to memory.<li>Support for files of any dimension (NAXIS).<li>Support for FITS extensions, including ASCII and binary tables.</ul>
|
||||
This library also comes with a limited set of interfaces to Python to make some of its functionalities usable from this language. See the compilation instructions to build it as a Python module.
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
<a name="history"><h2>History</h2></a>
|
||||
|
||||
<p>
|
||||
<b>qfits</b> was born from the need to have a simple but powerful C library to handle FITS file accesses. There are already many libraries on the Net to handle FITS files, but they tend to be bloated with far too many features and would cause lots of problems in including in our own software (mainly for portability).
|
||||
<p>
|
||||
<b>qfits</b> was written to take care of all low-level aspects of the FITS format, and only these. You will find there a wealth of optimized functions to access everything inside FITS files, but nothing about what you could do with the data, this is left to other (e.g. image processing) libraries. There is no suggested image or cube type, and the table object only loads the data without trying to interpret them.
|
||||
<p>
|
||||
The idea is that people wanting to work with FITS might have different requirements: somebody writing an image viewer might just want to load a pixel buffer, somebody handling headers only might want to have easy access to header information without touching pixel data. <b>qfits</b> allows you to get your hands on what is contained in a FITS file but does not force you to use any specific high-level data type to describe your data.
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
<a name="authors"><h2>Authors</h2></a>
|
||||
|
||||
<p>
|
||||
Nicolas Devillard and Yves Jung, ESO.
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
<a name="header"><h2>Header handling</h2></a>
|
||||
|
||||
<p>
|
||||
This section gives you an overview of the functionalities offered to work on FITS headers with <b>qfits</b>. For a complete reference, check out the manual generated from the header file: <a class="el" href="qfits_h.html">qfits.h</a>.
|
||||
<p>
|
||||
FITS headers are simply formatted as 80-char lines (cards) containing ancillary data represented in ASCII format like:
|
||||
<p>
|
||||
keyword = value / comment
|
||||
<p>
|
||||
If you want to retrieve data from a FITS file header, you will find various useful query routines to get a keyword value from main or extension headers. Values are returned as strings and not coerced to any particular (e.g. numerical) type. See e.g.
|
||||
<p>
|
||||
<ul>
|
||||
<li><a class="el" href="qfits_h.html#a48">qfits_query_hdr</a>() to query the main header.<li><a class="el" href="qfits_h.html#a49">qfits_query_ext</a>() to query an extension header.<li><a class="el" href="qfits_h.html#a50">qfits_query_n_ext</a>() to get the number of extensions.</ul>
|
||||
You may also want to handle file inputs by yourself and have FITS lines (called <em>cards</em> in FITS terminology) split into their components key/value/comment. See e.g.
|
||||
<p>
|
||||
<ul>
|
||||
<li><a class="el" href="qfits_h.html#a32">qfits_getkey</a>() extract the key from a FITS line.<li><a class="el" href="qfits_h.html#a33">qfits_getvalue</a>() extract the value.<li><a class="el" href="qfits_h.html#a34">qfits_getcomment</a>() extract the comment.</ul>
|
||||
Since all FITS values are returned as strings, you may need to identify types. See e.g.
|
||||
<p>
|
||||
<ul>
|
||||
<li><a class="el" href="qfits_h.html#a57">qfits_get_type</a>() identifies a value type<li><a class="el" href="qfits_h.html#a52">qfits_is_boolean</a>()<li><a class="el" href="qfits_h.html#a53">qfits_is_int</a>()<li><a class="el" href="qfits_h.html#a54">qfits_is_float</a>()<li><a class="el" href="qfits_h.html#a55">qfits_is_complex</a>()<li><a class="el" href="qfits_h.html#a56">qfits_is_string</a>()</ul>
|
||||
Of course, you can use the usual <code>atof()</code>, <code>atoi()</code> and <code>scanf()</code> functions to convert a string to a numerical type.
|
||||
<p>
|
||||
You may also want to perform more complex operations on FITS headers, like loading one, modifying it and saving it back to a new file. The qfits_header data structure is offered for that purpose. It comes with utilities like:
|
||||
<p>
|
||||
<ul>
|
||||
<li><a class="el" href="qfits_h.html#a35">qfits_header_read</a>() loads a header.<li><a class="el" href="qfits_h.html#a36">qfits_header_readext</a>() same from an extension.<li><a class="el" href="qfits_h.html#a29">qfits_header_dump</a>() saves a header to a file.<li>...</ul>
|
||||
And of course all manipulation tools you can think of:
|
||||
<p>
|
||||
<ul>
|
||||
<li><a class="el" href="qfits_h.html#a10">qfits_header_add</a>()<li><a class="el" href="qfits_h.html#a11">qfits_header_add_after</a>()<li><a class="el" href="qfits_h.html#a12">qfits_header_append</a>()<li><a class="el" href="qfits_h.html#a14">qfits_header_mod</a>()<li><a class="el" href="qfits_h.html#a13">qfits_header_del</a>()<li>...</ul>
|
||||
There are other functions to create new FITS cards, dump a header to screen for debugging purposes, etc. See <a class="el" href="qfits_h.html">qfits.h</a> for an exhaustive description.
|
||||
<p>
|
||||
An important feature of the qfits_header object when loaded from a file, is that it conserves the memory of the initial FITS card. The data structure that is carried around for each FITS card contains:
|
||||
<p>
|
||||
<ul>
|
||||
<li>Identified keyword<li>Identified value<li>Possible comment<li>Line as read from initial file when applicable.</ul>
|
||||
This feature is fairly useful if you want to perform header manipulation without getting too intrusive. You can use this to load a header, modify a couple of cards and dump all back to disk. The dumped header will only be modified for the cards you have touched, all others will be forwarded verbatim as they appeared in the initial file. This least-modification policy ensures that you will not modify the lines you do not need to touch.
|
||||
<p>
|
||||
This feature can be turned off by "touching" all lines in a header using <a class="el" href="qfits_h.html#a17">qfits_header_touchall</a>(), which removes all initial line information from a qfits_header object. This is useful to force a reformatting of a FITS header e.g. when the file header is damaged.
|
||||
<p>
|
||||
Notice that ESO's <code>HIERARCH</code> keywords and DICB ordering are natively supported by <b>qfits</b>, i.e. when you work with qfits_header objects you can be sure that they will properly recognize and order keywords following ESO conventions.
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
<a name="data"><h2>Data handling</h2></a>
|
||||
|
||||
<p>
|
||||
This section gives you an overview of the functionalities offered to work on FITS data segments with <b>qfits</b>. For a complete reference, check out the manual generated from the header file: <a class="el" href="qfits_h.html">qfits.h</a>.
|
||||
<p>
|
||||
Data segments are quite simply stored: they always contain data contiguously in uncompressed format, so reading them is mostly a matter of applying an <code>fread()</code> statement at the right place in the file, with the right size. To find out about offsets to data and header parts in a FITS file (possibly containing several extensions), you can make use of:
|
||||
<p>
|
||||
<ul>
|
||||
<li><a class="el" href="qfits_h.html#a58">qfits_get_hdrinfo</a>() returns information about a header position and size (in bytes) in a file.<li><a class="el" href="qfits_h.html#a59">qfits_get_datinfo</a>() returns information about a data segment position and size (in bytes) in a file.</ul>
|
||||
<b>qfits</b> includes a caching mechanism to accelerate accesses to large files to an optimal access time (only one parsing of the file is needed, even with multiple queries on the same file). This mechanism is internal to this module and used invisibly for the programmer using <b>qfits</b>. This means that you can loop on all sections on a huge file to retrieve file offsets for each extension, and pay the price of file parsing only at the first call.
|
||||
<p>
|
||||
If you want to dive further into data loading, you may want to have a look at table and image handling functionalities.
|
||||
<p>
|
||||
<a name="table"><h3>Table handling</h3></a>
|
||||
|
||||
<p>
|
||||
The qfits_table and qfits_col objects are offered to help you load table data into memory. I/O operators are e.g.
|
||||
<p>
|
||||
<ul>
|
||||
<li><a class="el" href="qfits_h.html#a64">qfits_table_open</a>() to load table information.<li><a class="el" href="qfits_h.html#a66">qfits_query_column</a>() to load column data into memory.</ul>
|
||||
The idea is that you first request general information about a table contained in a FITS file, then launch as many column queries as you need to retrieve the data. Data are byte-swapped if needed and returned as a pointer to void which must be cast to the proper data type (known from the column information tag).
|
||||
<p>
|
||||
Tables can of course be created from scratch and saved to disk or dumped to screen. See <a class="el" href="qfits_h.html">qfits.h</a> for a complete reference.
|
||||
<p>
|
||||
<a name="image"><h3>Image handling</h3></a>
|
||||
|
||||
<p>
|
||||
The qfitsloader and qfitsdumper objects are offered to simplify the action of reading/writing image data. The corresponding operators take care of retrieving all necessary ancillary information (image size, pixel type, buffer position), perform a memory allocation or mapping and read the file into memory. The returned data buffers can be chosen to be float, int, or double pixels. See e.g.
|
||||
<p>
|
||||
<ul>
|
||||
<li><a class="el" href="qfits_h.html#a39">qfitsloader_init</a>() to initialize a loader object.<li><a class="el" href="qfits_h.html#a40">qfits_loadpix</a>() to load pixel data into memory.<li><a class="el" href="qfits_h.html#a44">qfits_pixdump</a>() to save pixel data to disk.</ul>
|
||||
As for tables, the idea is that you first launch an analysis of the file to get back a number of informations about what is present there. In the case of images, you use <a class="el" href="qfits_h.html#a39">qfitsloader_init</a>() to see if pixel loading could be done, then use <a class="el" href="qfits_h.html#a40">qfits_loadpix</a>() to perform the actual load.
|
||||
<p>
|
||||
Pixel I/O are taking place in float, int or double format. See the corresponding functions:
|
||||
<p>
|
||||
<ul>
|
||||
<li><a class="el" href="qfits_h.html#a41">qfits_pixin_float</a>()<li><a class="el" href="qfits_h.html#a42">qfits_pixin_int</a>()<li><a class="el" href="qfits_h.html#a43">qfits_pixin_double</a>()<li><a class="el" href="qfits_h.html#a45">qfits_pixdump_float</a>()<li><a class="el" href="qfits_h.html#a46">qfits_pixdump_int</a>()<li><a class="el" href="qfits_h.html#a47">qfits_pixdump_double</a>()</ul>
|
||||
Loading pixels as floats means that whichever pixel format (BITPIX) is used in your input FITS file, all pixels will be converted to your local representation of float upon loading. The 3 offered types basically allow you to work with 3 kinds of pixels internally, choose the one that best suits your needs. 'int' is not recommended for loss of precision, and 'double' for memory and performance issues.
|
||||
<p>
|
||||
Saving pixels can be done with any BITPIX setting. There are 3 pixel dumpers as there are 3 pixel loaders because your pixel buffer to save might be stored in any of the 3 supported types. All pixels are converted on the fly to the requested BITPIX setting.
|
||||
<p>
|
||||
Notice that as soon as you start using pixel loading functions, you must comply with the <b>qfits</b> memory model. This basically means that you should not only include <code><a class="el" href="qfits_h.html">qfits.h</a></code> in your program, but also <code>xmemory.h</code> to get the proper definitions for memory allocation functions.
|
||||
<p>
|
||||
<a name="utils"><h2>Other utilities</h2></a>
|
||||
|
||||
<p>
|
||||
Some additional functions are offered in <b>qfits</b>, they are useful in the VLT context. See:
|
||||
<p>
|
||||
<ul>
|
||||
<li><a class="el" href="qfits_h.html#a72">date_now</a>()<li><a class="el" href="qfits_h.html#a73">time_now</a>()<li><a class="el" href="qfits_h.html#a74">get_date_iso8601</a>()<li><a class="el" href="qfits_h.html#a75">get_datetime_iso8601</a>()</ul>
|
||||
<hr>
|
||||
<p>
|
||||
<a name="features"><h2>Features</h2></a>
|
||||
|
||||
<p>
|
||||
Some of the unique features of this library are:
|
||||
<p>
|
||||
<a name="portability"><h3>Portability</h3></a>
|
||||
|
||||
<p>
|
||||
This library has been ported and tested on the following platforms:
|
||||
<p>
|
||||
<ul>
|
||||
<li>Linux x86 and alpha<li>Solaris 2.5, 2.6 and 2.8<li>HPUX 8, 9, 10, 11<li>AIX<li>BSD compatible, including Darwin (Mac OS X)<li>OSF/1 or Tru64</ul>
|
||||
Since <b>qfits</b> makes lots of calls to POSIX system routines, there is little chance it could compile natively on Windows, except with the help from GNU porting tools from Cygnus. This has never been attempted so far.
|
||||
<p>
|
||||
<a name="speed"><h3>Speed</h3></a>
|
||||
|
||||
<p>
|
||||
The offered routines are extremely fast, making use of caching mechanisms and memory-mapping system calls to enhance FITS file parsing.
|
||||
<p>
|
||||
<a name="interfaces"><h3>Interfaces to C++/Python</h3></a>
|
||||
|
||||
<p>
|
||||
You should be able to compile this library with a C++ compiler, the header files include the usual blurb to allow that without warning from the compiler. You might have problems due to pointer casts and other various incompatibilities due to the variety of C++ dialects and compilers, though. If you really need to hook this library into C++ code, your best bet is probably to compile the library as a standard C library and link your C++ code against it.
|
||||
<p>
|
||||
A limited set of interfaces to Python is offered. See the INSTALL file in the main distribution directory for instructions about installing this library as a Python module.
|
||||
<p>
|
||||
<a name="precision"><h3>Numerical precision</h3></a>
|
||||
|
||||
<p>
|
||||
Since FITS headers are stored as strings, numerical precision is limited by the number of digits used to write a number in a FITS card, which is in theory larger than what a 32-bit floating-point can store. Using <b>qfits</b>, these values are available to a C programmer as a string, making sure that precision has at least not be lost in the reading process.
|
||||
<p>
|
||||
<a name="conservative"><h3>Conservative headers</h3></a>
|
||||
|
||||
<p>
|
||||
As mentioned above, if you only need to load a header, modify a card and save it back, you will find out that <em>only</em> the card you touched has been modified, the rest was verbatim transferred. This is useful to ensure that the library formatting does not disturb your format.
|
||||
<p>
|
||||
<a name="hierarch"><h3>Native HIERARCH support</h3></a>
|
||||
|
||||
<p>
|
||||
Native support for ESO's <code>HIERARCH</code> keywords, as well as keywords of any length (up to 80 chars per line).
|
||||
<p>
|
||||
<a name="dicb"><h3>ESO/DICB keyword ordering</h3></a>
|
||||
|
||||
<p>
|
||||
Native support for DICB (ESO only) ordering of keywords in the headers. If you use this library to produce FITS files, you can reasonably be sure that all the files you create will be DICB compliant with respect to keyword ordering.
|
||||
<p>
|
||||
<a name="xmemory"><h3>Memory model</h3></a>
|
||||
|
||||
<p>
|
||||
<b>qfits</b> does not only offer pixel loading mechanisms, it also comes bundled with a memory module based on a model optimized for the handling of very large data segments. In practice, it means that as soon as you have included <code>xmemory.h</code>, your calls to malloc/calloc/free are re-directed to specific versions which put your program on steroids. Calls to memory allocators will yield valid data pointers past the hardware limits of your machine, up to 2 or 4 Gb on a 32-bit workstation and insanely high values on 64-bit processors.
|
||||
<p>
|
||||
This memory module is also distributed as a stand-alone module which can be downloaded and used without <b>qfits</b>. It is mandatory to use this module when using <b>qfits</b> pixel loaders, to get the advantages of large memory handling.
|
||||
<p>
|
||||
If you are only interested in header manipulation, you do not need to include <code>xmemory.h</code>.
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
<a name="install"><h2>Installation instructions</h2></a>
|
||||
|
||||
<p>
|
||||
In the main <b>qfits</b> directory, type:
|
||||
<p>
|
||||
<div class="fragment"><pre>
|
||||
./configure ; make
|
||||
</div></pre>
|
||||
<p>
|
||||
To use the library in your programs, add the following line on top of your module:
|
||||
<p>
|
||||
<div class="fragment"><pre><font class="preprocessor">#include "<a class="code" href="qfits_h.html">qfits.h</a>"</font></div></pre>
|
||||
<p>
|
||||
And link your program with the <b>qfits</b> library by adding <code>-lqfits</code> to the compile line.
|
||||
<p>
|
||||
If you ever need to make calls to one of the <b>qfits</b> pixel loaders, you need to include the memory model definitions also with:
|
||||
<p>
|
||||
<div class="fragment"><pre><font class="preprocessor">#include "xmemory.h"</font></div></pre>
|
||||
<p>
|
||||
Including this file is needed so that you can safely <code>free()</code> the pointer returned by a pixel loader. See the documentation about pixel loaders for more information.
|
||||
<p>
|
||||
To compile <b>qfits</b> as a Python module, you need to have Python installed on your machine and available in your PATH. Type:
|
||||
<p>
|
||||
<div class="fragment"><pre>
|
||||
% python setup.py install
|
||||
</div></pre>
|
||||
<p>
|
||||
This should build the module and install it in your default library path. This makes use of the distutils package, standardized since Python 2.0. This means that you need Python 2.0 at least to compile and run this module. If you are running Python 1.5 or 1.6, you may want to install the <code>distutils</code> package on your platform, which will handle the <b>qfits</b> module installation.
|
||||
<p>
|
||||
<hr>
|
||||
<p>
|
||||
<a name="faq"><h2>Frequently Asked Questions</h2></a>
|
||||
|
||||
<p>
|
||||
<a name="faq1"><h3>Where should I start to use qfits?</h3></a>
|
||||
|
||||
<p>
|
||||
Try to build the library on your system first. You should then have a new library file called libqfits.a. To use the library functionalities in your programs, you must add the following include in your list of includes:
|
||||
<p>
|
||||
<div class="fragment"><pre>
|
||||
#include "qfits.h"
|
||||
</div></pre>
|
||||
<p>
|
||||
And then compile your program adding the correct flags to indicate where the <b><a class="el" href="qfits_h.html">qfits.h</a></b> header file is, where the libqfits.a file is, and that you want to link against libqfits. Example: if the header file is in /usr/local/include and the library in /usr/local/lib, you would use:
|
||||
<p>
|
||||
<div class="fragment"><pre>
|
||||
% cc -o myprog myprog.c -I/usr/local/include -L/usr/local/lib -lqfits
|
||||
</div></pre>
|
||||
<p>
|
||||
<a name="faq2"><h3>What should I know about the cache mechanism?</h3></a>
|
||||
|
||||
<p>
|
||||
Parsing FITS files to find extensions is a lengthy process, because the FITS format does not declare in the main header where the following extensions are located in the file. Any access to a FITS file with this library will cache a number of offset pointers in the file to allow fast access to extensions. This means that the file is parsed completely only once, the first time it is accessed through any of the <b>qfits</b> functions.
|
||||
<p>
|
||||
This has two side-effects, due to the cache implementation. The cache is a memory buffer located inside the <b>qfits</b> library, which will grow for any new FITS file presented to its query functions. The amount of memory taken for each new file is small (less than 100 bytes), but will nonetheless accumulate if you start reading lots of new FITS files in an application that is meant to live a relatively long amount of time. To prevent the cache from growing indefinitely, a cache purging mechanism called <a class="el" href="qfits_h.html#a6">qfits_cache_purge</a>() is offered.
|
||||
<p>
|
||||
Purging will be called every time you reach 4096 FITS files in the cache, which corresponds roughly to 300 kbytes. If you are working with huge number of files simultaneously and need to access them often, you might want to increase this limit in cache.c. On the other hand, if you want to reduce the memory usage due to cache, you may want to reduce the corresponding limits accordingly, or purge more often.
|
||||
<p>
|
||||
The second side-effet is that the cache structure makes the cache module thread-unsafe. If you are concerned about writing multi-threaded applications, you should put a mutex on accessing this library. A thread-safe compliant version might become available some day, so if you want to help...
|
||||
<p>
|
||||
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,502 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta name="author" content="ndevil@eso.org">
|
||||
<meta name="editor" content="ndevil@eso.org">
|
||||
<meta name="maintainer" content="ndevil@eso.org">
|
||||
<meta name="organisation" content="ESO, DMD">
|
||||
<meta name="keywords" content="eso, FITS format, C library">
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||
<title>qfits 4.0</title>
|
||||
</head>
|
||||
|
||||
<body text="#000000" bgcolor="#ffffff">
|
||||
|
||||
|
||||
|
||||
<!-- Generated by Doxygen 1.2.5 on Wed Jan 23 15:41:02 2002 -->
|
||||
<h1>_qfits_col_ Struct Reference</h1>Column object.
|
||||
<a href="#_details">More...</a>
|
||||
<p>
|
||||
<code>#include <qfits.h></code>
|
||||
<p>
|
||||
<table border=0 cellpadding=0 cellspacing=0>
|
||||
<tr><td colspan=2><br><h2>Data Fields</h2></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m0">nelem</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m1">natoms</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m2">atom_size</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m3">ascii_size</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>char </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m4">atom_type</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m5">atom_nb</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>char </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m6">tlabel</a> [FITSVALSZ]</td></tr>
|
||||
<tr><td nowrap align=right valign=top>char </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m7">tunit</a> [FITSVALSZ]</td></tr>
|
||||
<tr><td nowrap align=right valign=top>char </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m8">nullval</a> [FITSVALSZ]</td></tr>
|
||||
<tr><td nowrap align=right valign=top>char </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m9">disp</a> [FITSVALSZ]</td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m10">zero_present</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>float </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m11">zero</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m12">scale_present</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>float </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m13">scale</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m14">off_beg</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m15">off_jmp</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_col_.html#m16">readable</a></td></tr>
|
||||
</table>
|
||||
<hr><a name="_details"></a><h2>Detailed Description</h2>
|
||||
Column object.
|
||||
<p>
|
||||
|
||||
<p>
|
||||
This structure contains all information needed to read a column in a table. These informations come from the header. The qfits_table object contains a list of qfits_col objects.
|
||||
<p>
|
||||
This structure has to be created from scratch and filled if one want to generate a FITS table.
|
||||
<p>
|
||||
<hr><h2>Field Documentation</h2>
|
||||
<a name="m3" doxytag="_qfits_col_::ascii_size"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_col_::ascii_size
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Only for ASCII fields (0 otherwise). Nb of characters of the field. </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m5" doxytag="_qfits_col_::atom_nb"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_col_::atom_nb
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Number of atoms per field as specified in TFORM keyword Differ from natoms for ASCII table fields of type different from A: you can have the string "1234" (natoms = 1) specified as I4 (atom_nb = 4) </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m2" doxytag="_qfits_col_::atom_size"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_col_::atom_size
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Size of one element in bytes. In ASCII tables, atom_size is the size of the element once it has been converted in its 'destination' type. For example, if "123" is contained in an ASCII table in a column defined as I type, natoms=1, ascii_size=3, atom_size=4. In ASCII tables:<ul>
|
||||
<li>type 'A' : atom_size = ascii_size = number of chars<li>type 'I', 'F' or 'E' : atom_size = 4<li>type 'D' : atom_size = 8 In BIN tables :<li>type 'A' : atom_size = ascii_size = atom_nb = number of chars<li>type 'L', 'X', B' : atom_size = 1<li>type 'I' : atom_size = 2<li>type 'E', 'J', 'C', 'P' : atom_size = 4<li>type 'D', 'M' : atom_size = 8 </ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m4" doxytag="_qfits_col_::atom_type"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
char _qfits_col_::atom_type
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Type of data in the column as specified in TFORM keyword In ASCII tables : A, I, F, E or D In BIN tables : L, X, B, I, J, A, E, D, C, M or P </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m9" doxytag="_qfits_col_::disp"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
char _qfits_col_::disp[FITSVALSZ]
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Display format </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m1" doxytag="_qfits_col_::natoms"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_col_::natoms
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Number of elements in one field. There are some differences according types <ul>
|
||||
<li>If the field contains a string, natoms = 1. In this case, the number of characters is given by ascii_size.<li>If the field contains elements of types 'L', 'I', 'J', 'E', 'D' or 'B', natoms is simply the number of elements.<li>For complex types ('C' or 'M') natoms is the number of double or float (number of complex * 2).<li>If the field contains elements of type P (pair of int), natoms is the number of int (nb of 'P' element * 2) </ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m0" doxytag="_qfits_col_::nelem"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_col_::nelem
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Number of rows in the column. In a same table, all columns have the same nelem value. </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m8" doxytag="_qfits_col_::nullval"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
char _qfits_col_::nullval[FITSVALSZ]
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Null value </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m14" doxytag="_qfits_col_::off_beg"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_col_::off_beg
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Offset between the beg. of the table and the beg. of the column. </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m15" doxytag="_qfits_col_::off_jmp"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_col_::off_jmp
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Width of the table in bytes </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m16" doxytag="_qfits_col_::readable"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_col_::readable
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Flag to know if the column is readable. An empty col is not readable </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m13" doxytag="_qfits_col_::scale"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
float _qfits_col_::scale
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m12" doxytag="_qfits_col_::scale_present"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_col_::scale_present
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m6" doxytag="_qfits_col_::tlabel"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
char _qfits_col_::tlabel[FITSVALSZ]
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Label of the column </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m7" doxytag="_qfits_col_::tunit"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
char _qfits_col_::tunit[FITSVALSZ]
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Unit of the data </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m11" doxytag="_qfits_col_::zero"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
float _qfits_col_::zero
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m10" doxytag="_qfits_col_::zero_present"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_col_::zero_present
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
zero and scale are used when the quantity in the field does not represent a true physical quantity. Basically, thez should be used when they are present: physical_value = zero + scale * field_value They are read from TZERO and TSCAL in the header </td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>The documentation for this struct was generated from the following file:<ul>
|
||||
<li><a class="el" href="qfits_h.html">qfits.h</a></ul>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,118 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta name="author" content="ndevil@eso.org">
|
||||
<meta name="editor" content="ndevil@eso.org">
|
||||
<meta name="maintainer" content="ndevil@eso.org">
|
||||
<meta name="organisation" content="ESO, DMD">
|
||||
<meta name="keywords" content="eso, FITS format, C library">
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||
<title>qfits 4.0</title>
|
||||
</head>
|
||||
|
||||
<body text="#000000" bgcolor="#ffffff">
|
||||
|
||||
|
||||
|
||||
<!-- Generated by Doxygen 1.2.5 on Wed Jan 23 15:41:02 2002 -->
|
||||
<h1>_qfits_header_ Struct Reference</h1>FITS header object.
|
||||
<a href="#_details">More...</a>
|
||||
<p>
|
||||
<code>#include <qfits.h></code>
|
||||
<p>
|
||||
<table border=0 cellpadding=0 cellspacing=0>
|
||||
<tr><td colspan=2><br><h2>Data Fields</h2></td></tr>
|
||||
<tr><td nowrap align=right valign=top>void* </td><td valign=bottom><a class="el" href="struct__qfits_header_.html#m0">first</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>void* </td><td valign=bottom><a class="el" href="struct__qfits_header_.html#m1">last</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_header_.html#m2">n</a></td></tr>
|
||||
</table>
|
||||
<hr><a name="_details"></a><h2>Detailed Description</h2>
|
||||
FITS header object.
|
||||
<p>
|
||||
|
||||
<p>
|
||||
This structure represents a FITS header in memory. It is actually no more than a thin layer on top of the keytuple object. No field in this structure should be directly modifiable by the user, only through accessor functions.
|
||||
<p>
|
||||
<hr><h2>Field Documentation</h2>
|
||||
<a name="m0" doxytag="_qfits_header_::first"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
void * _qfits_header_::first
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m1" doxytag="_qfits_header_::last"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
void * _qfits_header_::last
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m2" doxytag="_qfits_header_::n"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_header_::n
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>The documentation for this struct was generated from the following file:<ul>
|
||||
<li><a class="el" href="qfits_h.html">qfits.h</a></ul>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,163 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta name="author" content="ndevil@eso.org">
|
||||
<meta name="editor" content="ndevil@eso.org">
|
||||
<meta name="maintainer" content="ndevil@eso.org">
|
||||
<meta name="organisation" content="ESO, DMD">
|
||||
<meta name="keywords" content="eso, FITS format, C library">
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||
<title>qfits 4.0</title>
|
||||
</head>
|
||||
|
||||
<body text="#000000" bgcolor="#ffffff">
|
||||
|
||||
|
||||
|
||||
<!-- Generated by Doxygen 1.2.5 on Wed Jan 23 15:41:02 2002 -->
|
||||
<h1>_qfits_table_ Struct Reference</h1>Table object.
|
||||
<a href="#_details">More...</a>
|
||||
<p>
|
||||
<code>#include <qfits.h></code>
|
||||
<p>
|
||||
<table border=0 cellpadding=0 cellspacing=0>
|
||||
<tr><td colspan=2><br><h2>Data Fields</h2></td></tr>
|
||||
<tr><td nowrap align=right valign=top>char </td><td valign=bottom><a class="el" href="struct__qfits_table_.html#m0">filename</a> [FILENAMESZ]</td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_table_.html#m1">tab_t</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfits_table_.html#m2">nc</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top><a class="el" href="qfits_h.html#a3">qfits_col</a>* </td><td valign=bottom><a class="el" href="struct__qfits_table_.html#m3">col</a></td></tr>
|
||||
</table>
|
||||
<hr><a name="_details"></a><h2>Detailed Description</h2>
|
||||
Table object.
|
||||
<p>
|
||||
|
||||
<p>
|
||||
This structure contains all information needed to read a FITS table. These information come from the header. The object is created by qfits_open().
|
||||
<p>
|
||||
To read a FITS table, here is a code example: <div class="fragment"><pre> <font class="keywordtype">int</font> main(<font class="keywordtype">int</font> argc, <font class="keywordtype">char</font>* argv[])<font class="keyword"></font>
|
||||
<font class="keyword"> </font>{
|
||||
<a class="code" href="struct__qfits_table_.html">qfits_table</a> * table ;
|
||||
<font class="keywordtype">int</font> n_ext ;
|
||||
<font class="keywordtype">int</font> i ;
|
||||
|
||||
n_ext = <a class="code" href="qfits_h.html#a50">qfits_query_n_ext</a>(argv[1]);
|
||||
<font class="keywordflow">for</font> (i=0 ; i<n_ext ; i++) {
|
||||
<font class="keywordflow">if</font> ((table = <a class="code" href="qfits_h.html#a64">qfits_table_open</a>(argv[1], i+1)) == NULL) {
|
||||
printf(<font class="stringliteral">"cannot open table [%s]:[%d]\n"</font>, argv[1], i+1);
|
||||
} <font class="keywordflow">else</font> {
|
||||
dump_extension(table, stdout, <font class="charliteral">'|'</font>, 1, 1) ;
|
||||
<a class="code" href="qfits_h.html#a65">qfits_table_close</a>(table) ;
|
||||
}
|
||||
}
|
||||
<font class="keywordflow">return</font> ;
|
||||
}</div></pre>
|
||||
<p>
|
||||
<hr><h2>Field Documentation</h2>
|
||||
<a name="m3" doxytag="_qfits_table_::col"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
<a class="el" href="qfits_h.html#a3">qfits_col</a> * _qfits_table_::col
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Array of qfits_col objects </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m0" doxytag="_qfits_table_::filename"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
char _qfits_table_::filename[FILENAMESZ]
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Name of the file the table comes from or it is intended to end to </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m2" doxytag="_qfits_table_::nc"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_table_::nc
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Number of columns </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m1" doxytag="_qfits_table_::tab_t"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfits_table_::tab_t
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Table type. Possible values are QFITS_INVALIDTABLE, QFITS_BINTABLE or QFITS_ASCIITABLE </td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>The documentation for this struct was generated from the following file:<ul>
|
||||
<li><a class="el" href="qfits_h.html">qfits.h</a></ul>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,253 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta name="author" content="ndevil@eso.org">
|
||||
<meta name="editor" content="ndevil@eso.org">
|
||||
<meta name="maintainer" content="ndevil@eso.org">
|
||||
<meta name="organisation" content="ESO, DMD">
|
||||
<meta name="keywords" content="eso, FITS format, C library">
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||
<title>qfits 4.0</title>
|
||||
</head>
|
||||
|
||||
<body text="#000000" bgcolor="#ffffff">
|
||||
|
||||
|
||||
|
||||
<!-- Generated by Doxygen 1.2.5 on Wed Jan 23 15:41:02 2002 -->
|
||||
<h1>_qfitsdumper_ Struct Reference</h1>qfits dumper control object.
|
||||
<a href="#_details">More...</a>
|
||||
<p>
|
||||
<code>#include <qfits.h></code>
|
||||
<p>
|
||||
<table border=0 cellpadding=0 cellspacing=0>
|
||||
<tr><td colspan=2><br><h2>Data Fields</h2></td></tr>
|
||||
<tr><td nowrap align=right valign=top>char* </td><td valign=bottom><a class="el" href="struct__qfitsdumper_.html#m0">filename</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsdumper_.html#m1">npix</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsdumper_.html#m2">ptype</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int* </td><td valign=bottom><a class="el" href="struct__qfitsdumper_.html#m3">ibuf</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>float* </td><td valign=bottom><a class="el" href="struct__qfitsdumper_.html#m4">fbuf</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>double* </td><td valign=bottom><a class="el" href="struct__qfitsdumper_.html#m5">dbuf</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsdumper_.html#m6">out_ptype</a></td></tr>
|
||||
</table>
|
||||
<hr><a name="_details"></a><h2>Detailed Description</h2>
|
||||
qfits dumper control object.
|
||||
<p>
|
||||
|
||||
<p>
|
||||
This structure offers various control parameters to dump a pixel buffer to a FITS file. The buffer will be dumped as requested to the requested file in append mode. Of course, the requested file must be writeable for the operation to succeed.
|
||||
<p>
|
||||
The following example demonstrates how to save a linear ramp sized 100x100 to a FITS file with BITPIX=16. Notice that this code only dumps the pixel buffer, no header information is provided in this case.
|
||||
<p>
|
||||
<div class="fragment"><pre> <font class="keywordtype">int</font> i, j ;
|
||||
<font class="keywordtype">int</font> * ibuf ;
|
||||
<a class="code" href="struct__qfitsdumper_.html">qfitsdumper</a> qd ;
|
||||
|
||||
<font class="comment">// Fill a buffer with 100x100 int pixels</font>
|
||||
ibuf = malloc(100 * 100 * <font class="keyword">sizeof</font>(<font class="keywordtype">int</font>));
|
||||
<font class="keywordflow">for</font> (j=0 ; j<100 ; j++) {
|
||||
<font class="keywordflow">for</font> (i=0 ; i<100 ; i++) {
|
||||
ibuf[i+j*100] = i+j ;
|
||||
}
|
||||
}
|
||||
|
||||
qd.filename = <font class="stringliteral">"out.fits"</font> ; <font class="comment">// Output file name</font>
|
||||
qd.npix = 100 * 100 ; <font class="comment">// Number of pixels</font>
|
||||
qd.ptype = PTYPE_INT ; <font class="comment">// Input buffer type</font>
|
||||
qd.ibuf = ibuf ; <font class="comment">// Set buffer pointer</font>
|
||||
qd.out_ptype = BPP_16_SIGNED ; <font class="comment">// Save with BITPIX=16</font>
|
||||
|
||||
<font class="comment">// Dump buffer to file (error checking omitted for clarity)</font>
|
||||
<a class="code" href="qfits_h.html#a44">qfits_pixdump</a>(&qd);
|
||||
|
||||
free(ibuf);</div></pre>
|
||||
<p>
|
||||
If the provided output file name is "STDOUT" (all capitals), the function will dump the pixels to the stdout steam (usually the console, could have been re-directed).
|
||||
<p>
|
||||
<hr><h2>Field Documentation</h2>
|
||||
<a name="m5" doxytag="_qfitsdumper_::dbuf"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
double * _qfitsdumper_::dbuf
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Pointer to input double pixel buffer </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m4" doxytag="_qfitsdumper_::fbuf"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
float * _qfitsdumper_::fbuf
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Pointer to input float pixel buffer </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m0" doxytag="_qfitsdumper_::filename"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
char * _qfitsdumper_::filename
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Name of the file to dump to, "STDOUT" to dump to stdout </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m3" doxytag="_qfitsdumper_::ibuf"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int * _qfitsdumper_::ibuf
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Pointer to input integer pixel buffer </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m1" doxytag="_qfitsdumper_::npix"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsdumper_::npix
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Number of pixels in the buffer to dump </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m6" doxytag="_qfitsdumper_::out_ptype"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsdumper_::out_ptype
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Requested BITPIX in output FITS file </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m2" doxytag="_qfitsdumper_::ptype"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsdumper_::ptype
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Buffer type: PTYPE_FLOAT, PTYPE_INT or PTYPE_DOUBLE </td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>The documentation for this struct was generated from the following file:<ul>
|
||||
<li><a class="el" href="qfits_h.html">qfits.h</a></ul>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,515 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta name="author" content="ndevil@eso.org">
|
||||
<meta name="editor" content="ndevil@eso.org">
|
||||
<meta name="maintainer" content="ndevil@eso.org">
|
||||
<meta name="organisation" content="ESO, DMD">
|
||||
<meta name="keywords" content="eso, FITS format, C library">
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||
<title>qfits 4.0</title>
|
||||
</head>
|
||||
|
||||
<body text="#000000" bgcolor="#ffffff">
|
||||
|
||||
|
||||
|
||||
<!-- Generated by Doxygen 1.2.5 on Wed Jan 23 15:41:02 2002 -->
|
||||
<h1>_qfitsloader_ Struct Reference</h1>qfits loader control object.
|
||||
<a href="#_details">More...</a>
|
||||
<p>
|
||||
<code>#include <qfits.h></code>
|
||||
<p>
|
||||
<table border=0 cellpadding=0 cellspacing=0>
|
||||
<tr><td colspan=2><br><h2>Data Fields</h2></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m0">_init</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>char* </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m1">filename</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m2">xtnum</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m3">pnum</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m4">ptype</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m5">exts</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m6">lx</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m7">ly</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m8">np</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m9">bitpix</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m10">seg_start</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>double </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m11">bscale</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>double </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m12">bzero</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>int* </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m13">ibuf</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>float* </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m14">fbuf</a></td></tr>
|
||||
<tr><td nowrap align=right valign=top>double* </td><td valign=bottom><a class="el" href="struct__qfitsloader_.html#m15">dbuf</a></td></tr>
|
||||
</table>
|
||||
<hr><a name="_details"></a><h2>Detailed Description</h2>
|
||||
qfits loader control object.
|
||||
<p>
|
||||
|
||||
<p>
|
||||
This structure serves two purposes: input and output for the qfits pixel loading facility. To request pixels from a FITS file, you need to allocate (statically or dynamically) such a structure and fill up the input fields (filename, xtension number, etc.) to specify the pixels you want from the file.
|
||||
<p>
|
||||
Before performing the actual load, you must pass the initialized structure to <a class="el" href="qfits_h.html#a39">qfitsloader_init</a>() which will check whether the operation is feasible or not (check its returned value).
|
||||
<p>
|
||||
If the operation was deemed feasible, you can proceed to load the pixels, passing the same structure to <a class="el" href="qfits_h.html#a40">qfits_loadpix</a>() which will fill up the output fields of the struct. Notice that a pixel buffer will have been allocated (through malloc or mmap) and placed into the structure. You need to call free() on this pointer when you are done with it, typically in the image or cube destructor.
|
||||
<p>
|
||||
The <a class="el" href="qfits_h.html#a39">qfitsloader_init</a>() function is also useful to probe a FITS file for useful informations, like getting the size of images in the file, the pixel depth, or data offset.
|
||||
<p>
|
||||
Example of a code that prints out various informations about a plane to load, without actually loading it:
|
||||
<p>
|
||||
<div class="fragment"><pre><font class="keywordtype">int</font> main(<font class="keywordtype">int</font> argc, <font class="keywordtype">char</font> * argv[])<font class="keyword"></font>
|
||||
<font class="keyword"></font>{
|
||||
<a class="code" href="struct__qfitsloader_.html">qfitsloader</a> ql ;
|
||||
|
||||
ql.filename = argv[1] ;
|
||||
ql.xtnum = 0 ;
|
||||
ql.pnum = 0 ;
|
||||
|
||||
<font class="keywordflow">if</font> (<a class="code" href="qfits_h.html#a39">qfitsloader_init</a>(&ql)!=0) {
|
||||
printf(<font class="stringliteral">"cannot read info about %s\n"</font>, argv[1]);
|
||||
<font class="keywordflow">return</font> -1 ;
|
||||
}
|
||||
|
||||
printf( <font class="stringliteral">"file : %s"</font>
|
||||
<font class="stringliteral">"xtnum : %d"</font>
|
||||
<font class="stringliteral">"pnum : %d"</font>
|
||||
<font class="stringliteral">"# xtensions : %d"</font>
|
||||
<font class="stringliteral">"size X : %d"</font>
|
||||
<font class="stringliteral">"size Y : %d"</font>
|
||||
<font class="stringliteral">"planes : %d"</font>
|
||||
<font class="stringliteral">"bitpix : %d"</font>
|
||||
<font class="stringliteral">"datastart : %d"</font>
|
||||
<font class="stringliteral">"bscale : %g"</font>
|
||||
<font class="stringliteral">"bzero : %g"</font>,
|
||||
ql.filename,
|
||||
ql.xtnum,
|
||||
ql.pnum,
|
||||
ql.exts,
|
||||
ql.lx,
|
||||
ql.ly,
|
||||
ql.np,
|
||||
ql.bitpix,
|
||||
ql.seg_start,
|
||||
ql.bscale,
|
||||
ql.bzero);
|
||||
<font class="keywordflow">return</font> 0 ;
|
||||
}</div></pre>
|
||||
<p>
|
||||
<hr><h2>Field Documentation</h2>
|
||||
<a name="m0" doxytag="_qfitsloader_::_init"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsloader_::_init
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
Private field to see if structure has been initialized </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m9" doxytag="_qfitsloader_::bitpix"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsloader_::bitpix
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: BITPIX for this extension </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m11" doxytag="_qfitsloader_::bscale"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
double _qfitsloader_::bscale
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: BSCALE found for this extension </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m12" doxytag="_qfitsloader_::bzero"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
double _qfitsloader_::bzero
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: BZERO found for this extension </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m15" doxytag="_qfitsloader_::dbuf"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
double * _qfitsloader_::dbuf
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: Pointer to pixel buffer loaded as double values </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m5" doxytag="_qfitsloader_::exts"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsloader_::exts
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: Total number of extensions found in file </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m14" doxytag="_qfitsloader_::fbuf"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
float * _qfitsloader_::fbuf
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: Pointer to pixel buffer loaded as float values </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m1" doxytag="_qfitsloader_::filename"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
char * _qfitsloader_::filename
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
input: Name of the file you want to read pixels from </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m13" doxytag="_qfitsloader_::ibuf"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int * _qfitsloader_::ibuf
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: Pointer to pixel buffer loaded as integer values </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m6" doxytag="_qfitsloader_::lx"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsloader_::lx
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: Size in X of the requested plane </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m7" doxytag="_qfitsloader_::ly"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsloader_::ly
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: Size in Y of the requested plane </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m8" doxytag="_qfitsloader_::np"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsloader_::np
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: Number of planes present in this extension </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m3" doxytag="_qfitsloader_::pnum"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsloader_::pnum
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
input: Index of the plane you want, from 0 to np-1 </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m4" doxytag="_qfitsloader_::ptype"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsloader_::ptype
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
input: Pixel type you want (PTYPE_FLOAT, PTYPE_INT or PTYPE_DOUBLE) </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m10" doxytag="_qfitsloader_::seg_start"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsloader_::seg_start
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
output: Start of the data segment (in bytes) for your request </td>
|
||||
</tr>
|
||||
</table>
|
||||
<a name="m2" doxytag="_qfitsloader_::xtnum"></a><p>
|
||||
<table width="100%" cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="md">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td nowrap valign="top"><b>
|
||||
int _qfitsloader_::xtnum
|
||||
</b></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table cellspacing=5 cellpadding=0 border=0>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
<p>
|
||||
input: xtension number you want to read </td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>The documentation for this struct was generated from the following file:<ul>
|
||||
<li><a class="el" href="qfits_h.html">qfits.h</a></ul>
|
||||
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,175 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file xmemory.h
|
||||
@author Nicolas Devillard
|
||||
@date Oct 2000
|
||||
@version $Revision: 1.14 $
|
||||
@brief POSIX-compatible extended memory handling.
|
||||
|
||||
xmemory is a small and efficient module offering memory
|
||||
extension capabitilies to ANSI C programs running on
|
||||
POSIX-compliant systems. If offers several useful features such
|
||||
as memory leak detection, protection for free on NULL or
|
||||
unallocated pointers, and virtually unlimited memory space.
|
||||
xmemory requires the @c mmap() system call to be implemented in
|
||||
the local C library to function. This module has been tested on
|
||||
a number of current Unix flavours and is reported to work fine.
|
||||
|
||||
See the documentation attached to this module for more information.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: xmemory.h,v 1.14 2002/01/10 08:53:43 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:43 $
|
||||
$Revision: 1.14 $
|
||||
*/
|
||||
|
||||
#ifndef _XMEMORY_H_
|
||||
#define _XMEMORY_H_
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
The following symbol is useful to know if the current module has been
|
||||
linked against xmemory.c or not.
|
||||
*/
|
||||
#define _XMEMORY_ 1
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Macros
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Protect strdup redefinition on systems which #define it rather than
|
||||
having it as a function.
|
||||
*/
|
||||
|
||||
#ifdef strdup
|
||||
#undef strdup
|
||||
#endif
|
||||
|
||||
#define malloc(s) xmemory_malloc(s, __FILE__,__LINE__)
|
||||
#define calloc(n,s) xmemory_calloc(n,s, __FILE__,__LINE__)
|
||||
#define free(p) xmemory_free(p, __FILE__,__LINE__)
|
||||
#define strdup(s) xmemory_strdup(s, __FILE__,__LINE__)
|
||||
#define falloc(f,o,s) xmemory_falloc(f,o,s, __FILE__,__LINE__)
|
||||
|
||||
/*
|
||||
Trick to have xmemory status display the file name and line where it has
|
||||
been called.
|
||||
*/
|
||||
#define xmemory_status() xmemory_status_(__FILE__,__LINE__)
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
void * xmemory_malloc(size_t, char *, int);
|
||||
void * xmemory_calloc(size_t, size_t, char *, int);
|
||||
void xmemory_free(void *, char *, int);
|
||||
char * xmemory_strdup(char *, char *, int);
|
||||
char * xmemory_falloc(char *, size_t, size_t *, char *, int);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Activate xmemory
|
||||
@return void
|
||||
|
||||
This function activates xmemory activity. Make sure it is always
|
||||
used consistently with xmemory_off().
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void xmemory_on(void);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Deactivate xmemory
|
||||
@return void
|
||||
|
||||
This function deactivates xmemory activity. Make sure it is always
|
||||
used consistently with xmemory_on().
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void xmemory_off(void);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Display memory status information.
|
||||
@return void
|
||||
|
||||
This function is meant for debugging purposes, but it is recommended to
|
||||
call it at the end of every executable making use of the extended memory
|
||||
features. This function should be called through the xmemory_status()
|
||||
macro, which provides automatically the name of the source file and line
|
||||
number where the call happens.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void xmemory_status_(char * filename, int lineno);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Set name of temporary directory for VM files.
|
||||
@param dirname Name of assigned directory.
|
||||
@return void
|
||||
|
||||
This function assigns a new value for the temporary directory name.
|
||||
It does not check the directory existence or writability, this is
|
||||
up to the caller to check that before calling this function.
|
||||
Provide a directory name without trailing slash, e.g. "/tmp".
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void xmemory_settmpdir(char * dirname);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Get name of temporary directory for VM files.
|
||||
@return pointer to statically allocated string within this module.
|
||||
|
||||
This function returns a pointer to an internal (static) string giving the
|
||||
current name for temporary directory. Do not modify or try to free the
|
||||
returned string.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * xmemory_gettmpdir(void);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Map a file's contents to memory as a char pointer.
|
||||
@param name Name of the file to map
|
||||
@param offs Offset to the first mapped byte in file.
|
||||
@param size Returned size of the mapped file in bytes.
|
||||
@param srcname Name of the source file making the call.
|
||||
@param srclin Line # where the call was made.
|
||||
@return A pointer to char, to be freed using xmemory_free().
|
||||
|
||||
This function takes in input the name of a file. It tries to map the
|
||||
file into memory and if it succeeds, returns the file's contents as
|
||||
a char pointer. It also modifies the input filesize variable to be
|
||||
the size of the mapped file in bytes. This function is normally
|
||||
never directly called but through the falloc() macro.
|
||||
|
||||
The offset indicates the starting point for the mapping, i.e. if you
|
||||
are not interested in mapping the whole file but only from a given
|
||||
place.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
char * xmemory_falloc(char * name, size_t offs, size_t * size, char * srcname, int srclin);
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,38 @@
|
|||
#
|
||||
# qfits tools Makefile
|
||||
# N. Devillard
|
||||
#
|
||||
#
|
||||
|
||||
#
|
||||
# General definitions
|
||||
#
|
||||
|
||||
include ../config.make
|
||||
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
MV = mv
|
||||
BINDIR = ../bin
|
||||
|
||||
COMPF = $(CFLAGS) -I../include
|
||||
LINKF = $(CFLAGS) -L../lib -lqfits
|
||||
|
||||
default: all
|
||||
|
||||
|
||||
PROGS= $(BINDIR)/dtfits \
|
||||
$(BINDIR)/flipx
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
veryclean:
|
||||
@(echo "cleaning qfits programs...")
|
||||
@($(RM) $(PROGS))
|
||||
|
||||
|
||||
$(BINDIR)/dtfits: dtfits.c
|
||||
$(CC) $(COMPF) -o $(BINDIR)/dtfits dtfits.c $(LINKF)
|
||||
|
||||
$(BINDIR)/flipx: flipx.c
|
||||
$(CC) $(COMPF) -o $(BINDIR)/flipx flipx.c $(LINKF)
|
|
@ -0,0 +1,254 @@
|
|||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
File name : dtfits.c
|
||||
Author : N. Devillard
|
||||
Created on : July 1999
|
||||
Description : FITS table dump
|
||||
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: dtfits.c,v 1.7 2001/12/18 09:32:52 yjung Exp $
|
||||
$Author: yjung $
|
||||
$Date: 2001/12/18 09:32:52 $
|
||||
$Revision: 1.7 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "qfits.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private declarations
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static int dump_extension(qfits_table * tdesc, FILE * out, char separator,
|
||||
int data_only, int use_zero_scale) ;
|
||||
static void qfits_dump(char *, char *, int, char);
|
||||
|
||||
static void usage(char *pname) ;
|
||||
static char prog_desc[] = "FITS table dump" ;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Main code
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char name_i[FILENAMESZ] ;
|
||||
char name_o[FILENAMESZ] ;
|
||||
int i ;
|
||||
int data_only ;
|
||||
char separator ;
|
||||
|
||||
data_only = 0 ;
|
||||
separator = '|' ;
|
||||
|
||||
if (argc<2) {
|
||||
usage(argv[0]);
|
||||
}
|
||||
|
||||
i=1 ;
|
||||
while (i<argc) {
|
||||
if (!strcmp(argv[i], "--help") ||
|
||||
!strcmp(argv[i], "-h")) {
|
||||
usage(argv[0]);
|
||||
} else if (!strcmp(argv[i], "-d")) {
|
||||
data_only=1 ;
|
||||
} else if (!strcmp(argv[i], "-s")) {
|
||||
if ((i+1)>=argc) {
|
||||
fprintf(stderr, "option -s needs an argument\n");
|
||||
return -1 ;
|
||||
}
|
||||
i++ ;
|
||||
separator = argv[i][0] ;
|
||||
} else {
|
||||
break ;
|
||||
}
|
||||
i++ ;
|
||||
}
|
||||
if ((argc-i)<1) {
|
||||
fprintf(stderr, "missing input file name\n");
|
||||
return -1 ;
|
||||
}
|
||||
strcpy(name_i, argv[i]);
|
||||
i++ ;
|
||||
if ((argc-i)<1) {
|
||||
name_o[0] = 0 ;
|
||||
} else {
|
||||
strcpy(name_o, argv[i]);
|
||||
}
|
||||
|
||||
qfits_dump(name_i, name_o, data_only, separator);
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
/* This function only gives the usage for the program */
|
||||
static void usage(char *pname)
|
||||
{
|
||||
printf("%s -- %s\n", pname, prog_desc);
|
||||
printf(
|
||||
"use : %s [options] <FITS table> [out]\n"
|
||||
"options are:\n"
|
||||
"\t-d to dump data only (no headers)\n"
|
||||
"\t-s <char> to output data with separator <char>\n"
|
||||
"\n",
|
||||
pname);
|
||||
exit(0) ;
|
||||
}
|
||||
|
||||
static void qfits_dump(
|
||||
char * name_i,
|
||||
char * name_o,
|
||||
int data_only,
|
||||
char separator)
|
||||
{
|
||||
qfits_table * tdesc ;
|
||||
FILE * out ;
|
||||
int xtnum ;
|
||||
int n_ext ;
|
||||
|
||||
|
||||
/* Set where to send the output */
|
||||
if (name_o[0]==(char)0) {
|
||||
out = stdout ;
|
||||
} else {
|
||||
if ((out = fopen(name_o, "w"))==NULL) {
|
||||
fprintf(stderr, "cannot create output file [%s]\n", name_o);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
if (!data_only) {
|
||||
fprintf(out, "#\n");
|
||||
fprintf(out, "# file %s\n", name_i);
|
||||
}
|
||||
|
||||
/* Query number of extensions in the file */
|
||||
n_ext = qfits_query_n_ext(name_i);
|
||||
if (!data_only) {
|
||||
fprintf(out, "# extensions %d\n", n_ext);
|
||||
}
|
||||
/* If no extension, bail out */
|
||||
if (n_ext<1) {
|
||||
if (out!=stdout) fclose(out) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
/* Loop over all extensions */
|
||||
for (xtnum=1 ; xtnum<=n_ext ; xtnum++) {
|
||||
if (!data_only) {
|
||||
fprintf(out, "# --------------------------------------------\n");
|
||||
fprintf(out, "# XTENSION %d\n", xtnum);
|
||||
}
|
||||
if ((tdesc = qfits_table_open(name_i, xtnum)) == NULL) {
|
||||
printf("cannot open table [%s]:[%d]\n", name_i, xtnum);
|
||||
if (out!=stdout) fclose(out);
|
||||
return ;
|
||||
}
|
||||
|
||||
dump_extension(tdesc, out, separator, data_only, 1) ;
|
||||
qfits_table_close(tdesc);
|
||||
}
|
||||
fclose(out) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
static int dump_extension(
|
||||
qfits_table * tdesc,
|
||||
FILE * out,
|
||||
char separator,
|
||||
int data_only,
|
||||
int use_zero_scale)
|
||||
{
|
||||
void ** array ;
|
||||
qfits_col * col ;
|
||||
char * stw ;
|
||||
int * sizes ;
|
||||
char format[512] ;
|
||||
int i, j ;
|
||||
|
||||
if (!data_only) {
|
||||
fprintf(out, "# Number of columns %d\n", tdesc->nc);
|
||||
fprintf(out, "#\n");
|
||||
}
|
||||
|
||||
/* Loop over all columns for the current extension */
|
||||
array = malloc(tdesc->nc * sizeof(void*)) ;
|
||||
for (i=0 ; i<tdesc->nc ; i++) {
|
||||
/* Load the data of each column in array[] and find each */
|
||||
/* column width to justify in the out file. */
|
||||
if ((array[i] = qfits_query_column_data(tdesc, i, NULL)) == NULL) {
|
||||
fprintf(stderr, "warning: cannot read column %d\n", i+1) ;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the sizes of the columns */
|
||||
sizes = calloc(tdesc->nc, sizeof(int)) ;
|
||||
for (i=0 ; i<tdesc->nc ; i++) {
|
||||
if (array[i] == NULL) sizes[i] = 0 ;
|
||||
else {
|
||||
for (j=0 ; j<tdesc->col->nelem ; j++) {
|
||||
if ((stw = qfits_table_field_to_string(tdesc,
|
||||
i,
|
||||
j,
|
||||
array[i],
|
||||
use_zero_scale)) == NULL) {
|
||||
sizes[i] = 0 ;
|
||||
break ;
|
||||
} else {
|
||||
if (sizes[i] < (int)strlen(stw)) {
|
||||
sizes[i] = (int)strlen(stw) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Print out the column names */
|
||||
if (!data_only) {
|
||||
for (i=0 ; i<tdesc->nc ; i++) {
|
||||
col = tdesc->col + i ;
|
||||
if (sizes[i] != 0) {
|
||||
if (sizes[i] < strlen(col->tlabel))
|
||||
sizes[i] = (int)strlen(col->tlabel) ;
|
||||
sprintf(format, "%%%ds", sizes[i]) ;
|
||||
fprintf(out, format, col->tlabel);
|
||||
if (i!=(tdesc->nc-1)) printf("%c", separator);
|
||||
}
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
|
||||
/* Dump all columns, line by line */
|
||||
col = tdesc->col ;
|
||||
for (j=0 ; j<col->nelem ; j++) {
|
||||
for (i=0 ; i<tdesc->nc ; i++) {
|
||||
col = tdesc->col + i ;
|
||||
if ((stw = qfits_table_field_to_string(tdesc,
|
||||
i,
|
||||
j,
|
||||
array[i],
|
||||
use_zero_scale)) != NULL) {
|
||||
sprintf(format, "%%%ds", sizes[i]) ;
|
||||
fprintf(out, format, stw);
|
||||
if (i!=(tdesc->nc-1)) printf("%c", separator);
|
||||
}
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
for (i=0 ; i<tdesc->nc ; i++) {
|
||||
if (array[i] != NULL) free(array[i]);
|
||||
}
|
||||
free(array) ;
|
||||
free(sizes) ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
File name : flipx.c
|
||||
Author : N. Devillard
|
||||
Created on : July 2001
|
||||
Description : flip x axis in a FITS image.
|
||||
|
||||
This is an example use of the qfits library. This program expects
|
||||
a list of FITS file names in input. For each input file, it will
|
||||
flip the image contained in the main data section in the X direction,
|
||||
i.e. pixel (i,j) is swapped with pixel (lx-i, j).
|
||||
|
||||
The pixel loading mechanism is independent from endian-ness of the
|
||||
local host or FITS pixel type. This program offers a good overview
|
||||
of how to use qfits for pixel-level operations.
|
||||
|
||||
Notice that this program does not support cubes or image extensions,
|
||||
but could be easily extended to support that case.
|
||||
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: flipx.c,v 1.1 2001/12/14 09:53:21 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2001/12/14 09:53:21 $
|
||||
$Revision: 1.1 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "qfits.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Macros
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define ERRMSG(s) fprintf(stderr, "\tflipx error: %s\n", s)
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Swap pixels between position p1 and p2, regardless of the pixel
|
||||
* type and endian-ness of the local host.
|
||||
*/
|
||||
static void swap_pix(char * buf, int p1, int p2, int psize)
|
||||
{
|
||||
int i ;
|
||||
char c ;
|
||||
|
||||
for (i=0 ; i<psize ; i++) {
|
||||
c = buf[p1+i] ;
|
||||
buf[p1+i] = buf[p2+i];
|
||||
buf[p2+i] = c ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Main processing function. It expects one only file name
|
||||
* and will flip pixels on the input frame.
|
||||
*/
|
||||
static int fits_flip(char * pname, char * filename)
|
||||
{
|
||||
char * sval ;
|
||||
int dstart;
|
||||
int lx, ly ;
|
||||
int bpp ;
|
||||
int i, j ;
|
||||
char * buf ;
|
||||
char * fbuf ;
|
||||
int psize;
|
||||
struct stat fileinfo ;
|
||||
int fd ;
|
||||
|
||||
printf("%s: processing %s\n", pname, filename);
|
||||
|
||||
if (stat(filename, &fileinfo)!=0) {
|
||||
return -1 ;
|
||||
}
|
||||
if (fileinfo.st_size<1) {
|
||||
ERRMSG("cannot stat file");
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* Retrieve image attributes */
|
||||
if (is_fits_file(filename)!=1) {
|
||||
ERRMSG("not a FITS file");
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
sval = qfits_query_hdr(filename, "NAXIS1");
|
||||
if (sval==NULL) {
|
||||
ERRMSG("cannot read NAXIS1");
|
||||
return -1 ;
|
||||
}
|
||||
lx = atoi(sval);
|
||||
sval = qfits_query_hdr(filename, "NAXIS2");
|
||||
if (sval==NULL) {
|
||||
ERRMSG("cannot read NAXIS2");
|
||||
return -1 ;
|
||||
}
|
||||
ly = atoi(sval);
|
||||
sval = qfits_query_hdr(filename, "BITPIX");
|
||||
if (sval==NULL) {
|
||||
ERRMSG("cannot read BITPIX");
|
||||
return -1 ;
|
||||
}
|
||||
bpp = atoi(sval);
|
||||
|
||||
psize = bpp/8 ;
|
||||
if (psize<0) psize=-psize ;
|
||||
|
||||
/* Retrieve start of first data section */
|
||||
if (qfits_get_hdrinfo(filename, 0, &dstart, NULL)!=0) {
|
||||
ERRMSG("reading header information");
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* Map the input file in read/write mode (input file is modified) */
|
||||
if ((fd=open(filename, O_RDWR))==-1) {
|
||||
perror("open");
|
||||
ERRMSG("reading file");
|
||||
return -1 ;
|
||||
}
|
||||
fbuf = (char*)mmap(0,
|
||||
fileinfo.st_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
fd,
|
||||
0);
|
||||
if (fbuf==(char*)-1) {
|
||||
perror("mmap");
|
||||
ERRMSG("mapping file");
|
||||
return -1 ;
|
||||
}
|
||||
buf = fbuf + dstart ;
|
||||
|
||||
/* Double loop */
|
||||
for (j=0 ; j<ly ; j++) {
|
||||
for (i=0 ; i<lx/2 ; i++) {
|
||||
/* Swap bytes */
|
||||
swap_pix(buf, i*psize, (lx-i-1)*psize, psize);
|
||||
}
|
||||
buf += lx * psize ;
|
||||
}
|
||||
if (munmap(fbuf, fileinfo.st_size)!=0) {
|
||||
ERRMSG("unmapping file");
|
||||
return -1 ;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
main()
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
int i ;
|
||||
int err ;
|
||||
|
||||
if (argc<2) {
|
||||
printf("use: %s <list of FITS files...>\n", argv[0]);
|
||||
return 1 ;
|
||||
}
|
||||
err=0 ;
|
||||
for (i=1 ; i<argc ; i++) {
|
||||
err += fits_flip(argv[0], argv[i]) ;
|
||||
}
|
||||
if (err>0) {
|
||||
fprintf(stderr, "%s: %d error(s) occurred\n", argv[0], err);
|
||||
return -1 ;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
|
@ -0,0 +1,319 @@
|
|||
"""
|
||||
Qfits.py: a module to read header information from a FITS file.
|
||||
|
||||
This module offers a function to read all headers in a given
|
||||
FITS file and return them as a list of strings.
|
||||
"""
|
||||
|
||||
# $Id: Qfits.py,v 1.9 2002/01/08 09:41:47 ndevilla Exp $
|
||||
# $Author: ndevilla $
|
||||
# $Date: 2002/01/08 09:41:47 $
|
||||
# $Revision: 1.9 $
|
||||
|
||||
import qfits
|
||||
|
||||
def get_headers(filename):
|
||||
"""
|
||||
This function is the main operator in this module.
|
||||
Given a file name, it returns all header informations
|
||||
in a list of lists. The top list contains one element
|
||||
per found header, i.e. if the given file has 8 extensions,
|
||||
the top list contains 9 items (1 for the main header,
|
||||
8 for the extension headers). Each list contains
|
||||
in turn all informations about the corresponding
|
||||
headers as a list of tuples like
|
||||
|
||||
(key, value, comment)
|
||||
|
||||
Example:
|
||||
|
||||
The given FITS file contains 1 main header and 2
|
||||
extension headers given as follows:
|
||||
|
||||
--- main header
|
||||
SIMPLE = T / FITS format
|
||||
BITPIX = 8 / Bits per pixel
|
||||
NAXIS = 0 / No data
|
||||
...
|
||||
END
|
||||
|
||||
--- extension 1
|
||||
XTENSION = 'IMAGE' / Image extension
|
||||
BITPIX = 16 / Bits per pixel
|
||||
...
|
||||
END
|
||||
|
||||
--- extension 2
|
||||
XTENSION = 'IMAGE' / Image extension
|
||||
BITPIX = -32 / Bits per pixel
|
||||
...
|
||||
END
|
||||
|
||||
The returned list contains three items.
|
||||
The first one is a list corresponding to the
|
||||
main header, then come the two extension
|
||||
headers. The first list looks like:
|
||||
|
||||
[ ('SIMPLE','T','FITS format'),
|
||||
('BITPIX', '8', 'Bits per pixel'),
|
||||
('NAXIS', '0', 'No data'),
|
||||
...
|
||||
('END', '', '') ]
|
||||
|
||||
The extension lists look like this:
|
||||
|
||||
[ ('XTENSION', 'IMAGE', 'Image extension'),
|
||||
('BITPIX', '16', 'Bits per pixel'),
|
||||
...
|
||||
('END', '', '') ]
|
||||
|
||||
[ ('XTENSION', 'IMAGE', 'Image extension'),
|
||||
('BITPIX', '-32', 'Bits per pixel'),
|
||||
...
|
||||
('END', '', '') ]
|
||||
|
||||
In summary, if you want to get all FITS header informations
|
||||
from a FITS file, call this function with:
|
||||
|
||||
hdr = qfits.get_headers(filename)
|
||||
|
||||
This function will raise an IOError exception if the provided
|
||||
filename does not correspond to a valid file, and None if
|
||||
the file is not FITS.
|
||||
|
||||
If the load succeeded, you can access individual keywords
|
||||
with the following syntax:
|
||||
|
||||
hdr[extension][row][index]
|
||||
|
||||
Where:
|
||||
|
||||
extension runs from 0 to N_EXT (inclusive)
|
||||
row is the row number of the card
|
||||
index is 0 for the keyword, 1 for the value, 2 for the comment.
|
||||
|
||||
The number of FITS extensions found in the file is simply:
|
||||
len(hdr)-1
|
||||
|
||||
"""
|
||||
return qfits.get_headers(filename)
|
||||
|
||||
def expand_keyword(key):
|
||||
"""
|
||||
This function is useful to expand a given keyword into
|
||||
its FITS equivalent. What it does is simply bring the
|
||||
word to uppercase, then expand shortFITS words to HIERARCH
|
||||
ESO notation, like:
|
||||
|
||||
simple -> SIMPLE
|
||||
NaXiS -> NAXIS
|
||||
det.dit -> HIERARCH ESO DET DIT
|
||||
"""
|
||||
return qfits.expand_keyword(key)
|
||||
|
||||
def datamd5(filename):
|
||||
"""
|
||||
This function computes the MD5 signature of all data parts in a FITS
|
||||
file and returns a 32-char string containing the signature as an
|
||||
hexadecimal number (128 bits). It raises an IOError exception if the
|
||||
given filename does not correspond to a valid FITS file.
|
||||
"""
|
||||
return qfits.datamd5(filename)
|
||||
|
||||
def version():
|
||||
"""
|
||||
This function returns the version number of the
|
||||
underlying qfits module.
|
||||
"""
|
||||
return qfits.version()
|
||||
|
||||
class fitsinfo:
|
||||
"""
|
||||
The fitsinfo class encapsulates queries into a FITS header.
|
||||
|
||||
Initialize an instance by giving the name of a file, the following
|
||||
fields are then filled in:
|
||||
|
||||
- filename - Name of the file
|
||||
- n_ext - Number of FITS extensions in file
|
||||
- hdrs - List of headers
|
||||
- xtnum - Current extension number for get()
|
||||
|
||||
The following methods are offered:
|
||||
|
||||
* get()
|
||||
This method retrieves keyword information in a given instance.
|
||||
Provide one or more keywords to look for and this function will
|
||||
browse the hdrs list for matching keywords. This method returns a
|
||||
string if you requested only 1 keyword or a list of strings if you
|
||||
requested several keywords. A failed match returns None.
|
||||
|
||||
This method will only search for keywords in the xtnum extension.
|
||||
|
||||
get() supports the shortFITS notation, in which A.B.C is transformed
|
||||
into HIERARCH ESO A B C before lookup in the FITS header. Notice that
|
||||
the given strings are also converted to uppercase before the search
|
||||
is launched. See the function expand_keyword() in this module.
|
||||
|
||||
Returned string values are always pretty-formatted, i.e. something
|
||||
stored into a FITS string as 'o''hara' will be returned as o'hara.
|
||||
|
||||
Examples:
|
||||
|
||||
q = fitsinfo('vltframe.fits')
|
||||
q.get('simple') # returns 'T'
|
||||
q.get('simple', 'naxis') # returns ('T', '2')
|
||||
|
||||
To search for keywords in the 3rd extension:
|
||||
|
||||
q = fitsinfo('wfiframe.fits')
|
||||
q.xtnum = 3
|
||||
q.get('xtension') # returns 'IMAGE'
|
||||
q.get('det.chip3.id', 'bitpix')
|
||||
# returns ('ccd52', '16')
|
||||
|
||||
* datamd5()
|
||||
This method computes the MD5 signature of all the data parts of the
|
||||
given FITS file and returns it as a 32-char string containing a
|
||||
hexadecimal number on 128 bits.
|
||||
|
||||
"""
|
||||
def __init__(self, filename):
|
||||
"""
|
||||
Provide a filename to initialize the object.
|
||||
"""
|
||||
self.filename = filename
|
||||
self.hdrs = qfits.get_headers(filename)
|
||||
if not self.hdrs:
|
||||
raise IOError, "not a FITS file"
|
||||
self.n_ext = len(self.hdrs)-1
|
||||
self.xtnum = 0
|
||||
|
||||
def get(self, *keywords):
|
||||
"""
|
||||
Get a list of keyword values and return it as a list. If only one
|
||||
keyword is requested, the returned value is a single string (or
|
||||
None if the keyword was not found). If several keywords are passed,
|
||||
the returned value is a list of found values.
|
||||
|
||||
The search is only performed in the current extension (xtnum field
|
||||
in the class).
|
||||
"""
|
||||
retval = []
|
||||
for keyword in keywords:
|
||||
keyword = qfits.expand_keyword(keyword)
|
||||
if len(keyword)<1:
|
||||
retval.append(None)
|
||||
continue
|
||||
found=0
|
||||
for k in self.hdrs[self.xtnum]:
|
||||
if k[0] == keyword:
|
||||
found=1
|
||||
retval.append(k[1])
|
||||
break
|
||||
if not found:
|
||||
retval.append(None)
|
||||
if len(retval)==1:
|
||||
return retval[0]
|
||||
return retval
|
||||
|
||||
def __repr__(self):
|
||||
return "file: %s - %d extensions" % (self.filename, self.n_ext)
|
||||
|
||||
def datamd5(self):
|
||||
return qfits.datamd5(self.filename)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
# This short code demonstrates the module capabilities
|
||||
|
||||
import string, sys
|
||||
|
||||
if len(sys.argv)<2:
|
||||
print "provide a FITS file name as first argument"
|
||||
raise SystemExit
|
||||
|
||||
filename = sys.argv[1]
|
||||
try:
|
||||
# Try building an instance of fitsinfo
|
||||
q = fitsinfo(filename)
|
||||
except IOError:
|
||||
print "cannot read file", filename
|
||||
raise SystemExit
|
||||
|
||||
# Demonstrate string representation of the instance
|
||||
print `q`
|
||||
# Compute the DATAMD5 value for this file
|
||||
print "computing DATAMD5 for", q.filename, "..."
|
||||
md5hash = q.datamd5()
|
||||
print "DATAMD5 = '"+md5hash+"'"
|
||||
|
||||
|
||||
# Dump the first 3 cards in each header to console to show they have
|
||||
# been correctly loaded.
|
||||
xtnum=0
|
||||
for h in q.hdrs:
|
||||
print "-"*65
|
||||
print "header beginning for %s (ext %d):" % (q.filename, xtnum)
|
||||
print "-"*65
|
||||
for card in [h[0], h[1], h[2]]:
|
||||
print "key[%s] val[%s] com[%s]" % (card[0], card[1], card[2])
|
||||
print "..."
|
||||
print "-"*65
|
||||
xtnum = xtnum+1
|
||||
|
||||
#
|
||||
# And now, for something completely different...
|
||||
#
|
||||
# An interesting example: transform a list of fetched keywords into a
|
||||
# dictionary for easier parsing. The idea is to build a dictionary-like
|
||||
# object that will allow queries into FITS headers like:
|
||||
# lx, ly = d["naxis1"], d["naxis2"]
|
||||
|
||||
# Get Python version
|
||||
pyver = string.split(sys.version[:3], '.')
|
||||
# Until Python 2.1, dictionaries (as all built-in types) cannot be
|
||||
# directly subclassed but through the UserDict module.
|
||||
if pyver < ['2','2']:
|
||||
print "using Python version < 2.2 (%s)" % (sys.version[:3])
|
||||
# Import the UserDict module to enable method overloading.
|
||||
from UserDict import UserDict
|
||||
|
||||
# Build a class derived from the dictionary.
|
||||
class FITSdic(UserDict):
|
||||
# A query will pass the key through expand_keyword to make sure
|
||||
# we can request something using lowercase and shortFITS
|
||||
# notation.
|
||||
def __getitem__(self, key):
|
||||
return self.data[qfits.expand_keyword(key)]
|
||||
else:
|
||||
# Starting with Python 2.2, dictionaries can directly be subclassed.
|
||||
print "using Python version >= 2.2 (%s)" % (sys.version[:3])
|
||||
class FITSdic(dict):
|
||||
# A query will pass the key through expand_keyword to make sure
|
||||
# we can request something using lowercase and shortFITS
|
||||
# notation.
|
||||
def __getitem__(self, key):
|
||||
return dict.__getitem__(self, qfits.expand_keyword(key))
|
||||
|
||||
# Create one instance
|
||||
d = FITSdic()
|
||||
# Fill it up with values from the previously loaded main header
|
||||
for card in q.hdrs[0]:
|
||||
d[card[0]] = card[1]
|
||||
|
||||
# Now show keywords stored in a dictionary.
|
||||
# Protect against keys that are not in dictionary (raises KeyError):
|
||||
print "Main header info:"
|
||||
try:
|
||||
print "SIMPLE=", d["simple"]
|
||||
print "BITPIX=", d["bitpix"]
|
||||
print "NAXIS =", d["naxis"]
|
||||
print "RA =", d["ra"]
|
||||
print "DEC =", d["dec"]
|
||||
except KeyError, key:
|
||||
print "Key", key, "not found in header"
|
||||
|
||||
# That's all folks
|
||||
print "end of Qfits demo"
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
python/qfits interface
|
||||
----------------------
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
qfits is interfaced to Python as a C module to compile
|
||||
dynamically, and a high-level interface called Qfits.py. To build
|
||||
the module, you need the distutils module from Python (standard
|
||||
since version 2.0). The setup.py script takes care of all the
|
||||
gory details related to the compilation of a dynamic module for
|
||||
Python. To build, type:
|
||||
|
||||
% python setup.py build
|
||||
|
||||
This will create a build/ directory containing the compiled
|
||||
objects and the dynamic library. You can test it by going into
|
||||
the directory containing qfits.so, launching python and trying to
|
||||
import the module. This is how it appears on our Linux box:
|
||||
|
||||
|
||||
% cd build/lib.linux-i686-2.1
|
||||
% python
|
||||
Python 2.1 (#1, Apr 27 2001, 17:19:41)
|
||||
[GCC 2.95.3 19991030 (prerelease)] on linux2
|
||||
Type "copyright", "credits" or "license" for more information.
|
||||
>>> import qfits
|
||||
>>> print qfits.version()
|
||||
>>> 4.0
|
||||
|
||||
To install the module in your Python installation, go back to the
|
||||
qfits root directory (where the setup.py script lives) and type:
|
||||
|
||||
% python setup.py install
|
||||
|
||||
This will install the qfits.so and Qfits.py files into your
|
||||
Python tree, provided you have the access rights to do so.
|
||||
|
||||
|
||||
If you do not have the distutils module (e.g. your Python
|
||||
installation is 1.5 or older), you are in trouble :-)
|
||||
Simplest is probably either to switch to a newer Python release
|
||||
or to install a recent version of distutils on your machine. If
|
||||
you really cannot afford upgrading Python or installing
|
||||
distutils, there is still a possible handcrafted solution: build
|
||||
the shared library by yourself and install it where it should.
|
||||
Something along the lines of:
|
||||
|
||||
1. Make the library normally (make).
|
||||
2. Compile the Python wrapper in relocatable mode, something like:
|
||||
|
||||
% gcc -fpic -o src/qfits_wrap.o src/qfits_wrap.c [...]
|
||||
|
||||
You also need to specify a path to the Python include files in this
|
||||
command-line, e.g. if Python lives under /usr/python on your machine,
|
||||
you would add something like:
|
||||
|
||||
-I/usr/python/include/python1.5
|
||||
|
||||
3. Now you should have all qfits objects (src/*.o) compiled, including the
|
||||
wrapper file. You are ready to build a shared library. On Linux, this
|
||||
gives something like that:
|
||||
|
||||
% ld -shared -o lib/qfits.so src/*.o
|
||||
|
||||
4. Try it the newly compiled module:
|
||||
|
||||
% cd lib
|
||||
% python
|
||||
% import qfits
|
||||
|
||||
At that point, Python should load the qfits.so module in the current
|
||||
directory without complaint. If everything is Ok, you should be able
|
||||
to issue the following command:
|
||||
|
||||
>>> qfits.version()
|
||||
|
||||
5. Copy now the shared object and Qfits.py files to wherever your
|
||||
Python installation expects libraries to be found. This can be
|
||||
anywhere within your Python tree or any directory you like
|
||||
provided it is declared in your PYTHONPATH. Try now:
|
||||
|
||||
% python
|
||||
>>> import Qfits
|
||||
|
||||
If everything went fine, you should not get any error.
|
||||
|
||||
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
|
||||
The qfits.so shared library offers a number of FITS-header
|
||||
parsing services from the qfits library. Not all functionalities
|
||||
are present, though, only the ones related to FITS header parsing
|
||||
and browsing. If you really need to access and modify pixels from
|
||||
the Python level, you are doing something wrong: Python is a very
|
||||
high-level language not intended for pixel-level operations. If
|
||||
you need that level of functionality, do it in C.
|
||||
|
||||
To protect Python code from changes happening in the C library,
|
||||
the interface to use is not "qfits" but "Qfits", so in your code
|
||||
you should have written:
|
||||
|
||||
import Qfits
|
||||
|
||||
and not:
|
||||
|
||||
import qfits
|
||||
|
||||
The former is a pure Python interface offering a number of
|
||||
functions and classes to deal with FITS headers. The latter is
|
||||
the wrapper interface to the qfits C library. Any change
|
||||
happening at low-level in qfits will be propagated to Qfits so as
|
||||
to maintain a fixed programming interface. In theory, you should
|
||||
never have to rewrite code depending on Qfits.py unless there are
|
||||
major changes in there (as e.g. between qfits-3.0 and qfits-4.0).
|
||||
|
||||
|
||||
Class documentation
|
||||
-------------------
|
||||
|
||||
To get an overview of the classes and services offered by
|
||||
Qfits.py, read its docstrings. Example:
|
||||
|
||||
>>> import Qfits
|
||||
>>> print Qfits.__doc__
|
||||
|
||||
|
||||
The docstrings are also readable from 'pydoc' if this tool is
|
||||
installed on your machine. It allows to browse the documentation
|
||||
in a Web browser on your local machine and supports complex
|
||||
searches.
|
||||
|
||||
|
||||
Enjoy Qfits!
|
||||
N. Devillard
|
||||
Mon Dec 10 14:00:05 CET 2001
|
|
@ -0,0 +1,59 @@
|
|||
|
||||
#
|
||||
# Stand-alone FITS tools Makefile
|
||||
# N. Devillard
|
||||
#
|
||||
#
|
||||
|
||||
#
|
||||
# General definitions
|
||||
#
|
||||
|
||||
include ../config.make
|
||||
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
MV = mv
|
||||
BINDIR = ../bin
|
||||
|
||||
default: all
|
||||
|
||||
|
||||
PROGS = $(BINDIR)/dfits \
|
||||
$(BINDIR)/fitsort \
|
||||
$(BINDIR)/hierarch28 \
|
||||
$(BINDIR)/iofits \
|
||||
$(BINDIR)/replacekey \
|
||||
$(BINDIR)/fitsmd5
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
veryclean:
|
||||
@(echo "cleaning saft programs...")
|
||||
@($(RM) $(PROGS))
|
||||
|
||||
|
||||
$(BINDIR)/dfits: dfits.c
|
||||
@(echo "building $@ ...")
|
||||
@($(CC) $(CFLAGS) $(LFLAGS) -o $(BINDIR)/dfits dfits.c)
|
||||
|
||||
$(BINDIR)/fitsort: fitsort.c
|
||||
@(echo "building $@ ...")
|
||||
@($(CC) $(CFLAGS) $(LFLAGS) -o $(BINDIR)/fitsort fitsort.c)
|
||||
|
||||
$(BINDIR)/hierarch28: hierarch28.c
|
||||
@(echo "building $@ ...")
|
||||
@($(CC) $(CFLAGS) $(LFLAGS) -o $(BINDIR)/hierarch28 hierarch28.c)
|
||||
|
||||
$(BINDIR)/iofits: iofits.c
|
||||
@(echo "building $@ ...")
|
||||
@($(CC) $(CFLAGS) $(LFLAGS) -o $(BINDIR)/iofits iofits.c)
|
||||
|
||||
$(BINDIR)/replacekey: replacekey.c
|
||||
@(echo "building $@ ...")
|
||||
@($(CC) $(CFLAGS) $(LFLAGS) -o $(BINDIR)/replacekey replacekey.c)
|
||||
|
||||
$(BINDIR)/fitsmd5: fitsmd5.c
|
||||
@(echo "building $@ ...")
|
||||
@($(CC) $(CFLAGS) $(LFLAGS) -o $(BINDIR)/fitsmd5 fitsmd5.c)
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
File name : dfits.c
|
||||
Author : Nicolas Devillard
|
||||
Created on : 30 Mar 2000
|
||||
Description : FITS header display
|
||||
|
||||
Initial version from 1996.
|
||||
Rewritten from scratch to support FITS extensions.
|
||||
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: dfits.c,v 1.1 2001/12/14 09:15:19 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2001/12/14 09:15:19 $
|
||||
$Revision: 1.1 $
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LGTH 80
|
||||
#define MAGIC "SIMPLE ="
|
||||
|
||||
|
||||
void usage(char * pname);
|
||||
void parse_cmd_line(int, char **, int*, int*, int*);
|
||||
int dump_fits_filter(FILE*, int);
|
||||
int dump_fits(char *, int);
|
||||
char * rstrip(char *);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int xtnum ;
|
||||
int c_arg ;
|
||||
int filter ;
|
||||
int err ;
|
||||
|
||||
/* No arguments prints out a usage message */
|
||||
if (argc<2) {
|
||||
usage(argv[0]);
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
/* Parse command-line options */
|
||||
parse_cmd_line(argc, argv, &xtnum, &filter, &c_arg);
|
||||
|
||||
/* Filter mode: process data received from stdin */
|
||||
if (filter)
|
||||
return dump_fits_filter(stdin, xtnum);
|
||||
|
||||
/* Normal mode: loop on all file names given on command-line */
|
||||
err = 0 ;
|
||||
while (c_arg < argc) {
|
||||
err += dump_fits(argv[c_arg], xtnum);
|
||||
c_arg++;
|
||||
}
|
||||
return err ; /* Returns number of errors during process */
|
||||
}
|
||||
|
||||
void usage(char * pname)
|
||||
{
|
||||
printf(
|
||||
"\n\n"
|
||||
"usage: %s [-x xtnum] <list of FITS files>\n"
|
||||
"usage: %s [-x xtnum] -\n"
|
||||
"\n"
|
||||
"The former version expects file names.\n"
|
||||
"The latter expects data coming in from stdin.\n"
|
||||
"\n"
|
||||
"-x xtnum specifies the extension header to print\n"
|
||||
"-x 0 specifies main header + all extensions\n"
|
||||
"\n\n",
|
||||
pname, pname);
|
||||
}
|
||||
|
||||
void parse_cmd_line(
|
||||
int argc,
|
||||
char ** argv,
|
||||
int * xtnum,
|
||||
int * filter,
|
||||
int * c_arg
|
||||
)
|
||||
{
|
||||
*filter = 0;
|
||||
*xtnum = -1 ;
|
||||
*c_arg = argc-1 ;
|
||||
|
||||
/* If '-' is on the command-line, it must be the last argument */
|
||||
if (!strcmp(argv[argc-1], "-")) {
|
||||
*filter = 1 ;
|
||||
}
|
||||
/*
|
||||
* If -x xtnum is on the command-line, it must be the first two
|
||||
* arguments
|
||||
*/
|
||||
if (!strcmp(argv[1], "-x")) {
|
||||
*xtnum = atoi(argv[2]);
|
||||
*c_arg = 3 ;
|
||||
} else {
|
||||
*c_arg = 1 ;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Strip off all blank characters in a string from the right-side.
|
||||
*/
|
||||
char * rstrip(char * s)
|
||||
{
|
||||
int len ;
|
||||
if (s==NULL) return s ;
|
||||
len = strlen(s);
|
||||
if (len<1) return s ;
|
||||
len -- ;
|
||||
while (s[len]== ' ') {
|
||||
s[len]=(char)0 ;
|
||||
len --;
|
||||
}
|
||||
return s ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the requested header (main or extension) from a filename.
|
||||
*/
|
||||
int dump_fits(char * name, int xtnum)
|
||||
{
|
||||
FILE * in ;
|
||||
int err ;
|
||||
|
||||
if ((in=fopen(name, "r"))==NULL) {
|
||||
fprintf(stderr, "error: cannot open file [%s]\n", name);
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
printf("====> file %s (main) <====\n", name) ;
|
||||
err = dump_fits_filter(in, xtnum);
|
||||
fclose(in);
|
||||
return err ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the requested header (main or extension) from a FILE *
|
||||
*/
|
||||
int dump_fits_filter(FILE * in, int xtnum)
|
||||
{
|
||||
int n_xt ;
|
||||
char buf[LGTH+1];
|
||||
int err ;
|
||||
|
||||
/* Try getting the first 80 chars */
|
||||
memset(buf, 0, LGTH+1);
|
||||
if (fread(buf, sizeof(char), LGTH, in)!=LGTH) {
|
||||
fprintf(stderr, "error reading input\n");
|
||||
return 1;
|
||||
}
|
||||
/* Check that it is indeed FITS */
|
||||
if (strncmp(buf, MAGIC, strlen(MAGIC))) {
|
||||
fprintf(stderr, "not a FITS file\n");
|
||||
return 1 ;
|
||||
}
|
||||
if (xtnum<1) {
|
||||
/* Output main header */
|
||||
printf("%s\n", rstrip(buf));
|
||||
while ((err=fread(buf, sizeof(char), LGTH, in))==LGTH) {
|
||||
printf("%s\n", rstrip(buf));
|
||||
if (buf[0]=='E' &&
|
||||
buf[1]=='N' &&
|
||||
buf[2]=='D') {
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if (err!=LGTH) /* Read error */
|
||||
return 1 ;
|
||||
}
|
||||
if (xtnum<0)
|
||||
return 0 ;
|
||||
|
||||
n_xt=0 ;
|
||||
while (1) {
|
||||
/* Look for next XTENSION keyword */
|
||||
while ((err=fread(buf, sizeof(char), LGTH, in))==LGTH) {
|
||||
if (buf[0]=='X' &&
|
||||
buf[1]=='T' &&
|
||||
buf[2]=='E' &&
|
||||
buf[3]=='N' &&
|
||||
buf[4]=='S' &&
|
||||
buf[5]=='I' &&
|
||||
buf[6]=='O' &&
|
||||
buf[7]=='N') break ;
|
||||
}
|
||||
if (err==0) /* Nothing more to read */
|
||||
break ;
|
||||
|
||||
if (err!=LGTH) /* Read error */
|
||||
return 1 ;
|
||||
|
||||
n_xt++ ;
|
||||
if (xtnum==0 || xtnum==n_xt) {
|
||||
printf("====> xtension %d\n", n_xt) ;
|
||||
printf("%s\n", rstrip(buf));
|
||||
while ((err=fread(buf, sizeof(char), LGTH, in))==LGTH) {
|
||||
printf("%s\n", rstrip(buf));
|
||||
if (buf[0]=='E' &&
|
||||
buf[1]=='N' &&
|
||||
buf[2]=='D') break ;
|
||||
}
|
||||
}
|
||||
if (n_xt==xtnum)
|
||||
break ;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
|
@ -0,0 +1,763 @@
|
|||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
||||
File name : fitsmd5.c
|
||||
Author : N. Devillard
|
||||
Created on : May 2001
|
||||
Description : Display/Add/Update the DATAMD5 keyword/value
|
||||
|
||||
This is a stand-alone utility. Compile it with any ANSI C compiler:
|
||||
% cc -o fitsmd5 fitsmd5.c [optional optimization options]
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: fitsmd5.c,v 1.1 2001/12/14 09:15:19 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2001/12/14 09:15:19 $
|
||||
$Revision: 1.1 $
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
/* Definitions related to FITS */
|
||||
#define FITSLINESZ 80 /* a FITS line is 80 chars */
|
||||
#define FITSCARDS 36 /* 36 cards per block */
|
||||
#define FITSBLOCKSZ (FITSLINESZ*FITSCARDS) /* FITS block size=2880 */
|
||||
|
||||
/* Definitions related to MD5 */
|
||||
#define MD5HASHSZ 32 /* an MD5 key length is 32 bytes = 128 bits */
|
||||
|
||||
/* FITS keyword used to store MD5 key */
|
||||
#define FITSMD5KEY "DATAMD5 "
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
New types
|
||||
---------------------------------------------------------------------------*/
|
||||
/* The following types defined for MD5 computation only */
|
||||
typedef unsigned int word32 ;
|
||||
|
||||
struct MD5Context {
|
||||
word32 buf[4];
|
||||
word32 bits[2];
|
||||
unsigned char in[64];
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Private function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static void MD5Init(struct MD5Context *);
|
||||
static void MD5Update(struct MD5Context *, unsigned char *, unsigned);
|
||||
static void MD5Final(unsigned char *, struct MD5Context *);
|
||||
static void MD5Transform(word32 *, word32 *);
|
||||
static void byteReverse(unsigned char *, unsigned);
|
||||
|
||||
static int fits_md5_check(char *, int);
|
||||
static char * fits_pretty_string(char *);
|
||||
static char * fits_getvalue(char *);
|
||||
|
||||
static void usage(void);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Global variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static char * pname = NULL ;
|
||||
static char prog_desc[] = "Compute/Update the DATAMD5 keyword/value" ;
|
||||
static int silent_process=0 ;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
MD5 function code
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Reverse bytes in a 32-bit word. This code is harmless on little endian
|
||||
* machines.
|
||||
*/
|
||||
static void byteReverse(unsigned char *buf, unsigned longs)
|
||||
{
|
||||
word32 t;
|
||||
do {
|
||||
t = (word32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(word32 *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to MD5
|
||||
* initialization constants.
|
||||
*/
|
||||
static void MD5Init(struct MD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
static void MD5Update(struct MD5Context *ctx, unsigned char *buf, unsigned len)
|
||||
{
|
||||
register word32 t;
|
||||
|
||||
/* Update bitcount */
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((word32) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
if (t) {
|
||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t) {
|
||||
memmove(p, buf, len);
|
||||
return;
|
||||
}
|
||||
memmove(p, buf, t);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (word32 *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
while (len >= 64) {
|
||||
memmove(ctx->in, buf, 64);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (word32 *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
memmove(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
static void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
|
||||
{
|
||||
unsigned int count;
|
||||
unsigned char *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset(p, 0, count);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (word32 *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(ctx->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((word32 *) ctx->in)[14] = ctx->bits[0];
|
||||
((word32 *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform(ctx->buf, (word32 *) ctx->in);
|
||||
byteReverse((unsigned char *) ctx->buf, 4);
|
||||
memmove(digest, ctx->buf, 16);
|
||||
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void MD5Transform(word32 buf[4], word32 in[16])
|
||||
{
|
||||
register word32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
FITS-related functions
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* Pretty-print a FITS string value */
|
||||
static char * fits_pretty_string(char * s)
|
||||
{
|
||||
static char pretty[FITSLINESZ+1] ;
|
||||
int i,j ;
|
||||
|
||||
if (s==NULL) return NULL ;
|
||||
|
||||
pretty[0] = (char)0 ;
|
||||
if (s[0]!='\'') return s ;
|
||||
|
||||
/* skip first quote */
|
||||
i=1 ;
|
||||
j=0 ;
|
||||
/* trim left-side blanks */
|
||||
while (s[i]==' ') {
|
||||
if (i==(int)strlen(s)) break ;
|
||||
i++ ;
|
||||
}
|
||||
if (i>=(int)(strlen(s)-1)) return pretty ;
|
||||
/* copy string, changing double quotes to single ones */
|
||||
while (i<(int)strlen(s)) {
|
||||
if (s[i]=='\'') {
|
||||
i++ ;
|
||||
}
|
||||
pretty[j]=s[i];
|
||||
i++ ;
|
||||
j++ ;
|
||||
}
|
||||
/* NULL-terminate the pretty string */
|
||||
pretty[j+1]=(char)0;
|
||||
/* trim right-side blanks */
|
||||
j = (int)strlen(pretty)-1;
|
||||
while (pretty[j]==' ') j-- ;
|
||||
pretty[j+1]=(char)0;
|
||||
return pretty;
|
||||
}
|
||||
|
||||
|
||||
/* Get the FITS value in a FITS card */
|
||||
static char * fits_getvalue(char * line)
|
||||
{
|
||||
static char value[FITSLINESZ+1] ;
|
||||
int i ;
|
||||
int from, to ;
|
||||
int inq ;
|
||||
|
||||
if (line==NULL) {
|
||||
return NULL ;
|
||||
}
|
||||
memset(value, 0, FITSLINESZ+1);
|
||||
/* Get past the keyword */
|
||||
i=0 ;
|
||||
while (line[i]!='=' && i<FITSLINESZ) i++ ;
|
||||
if (i>FITSLINESZ) {
|
||||
return NULL ;
|
||||
}
|
||||
i++ ;
|
||||
while (line[i]==' ' && i<FITSLINESZ) i++ ;
|
||||
if (i>FITSLINESZ) {
|
||||
return NULL ;
|
||||
}
|
||||
from=i;
|
||||
/*
|
||||
* Now in the value section
|
||||
* Look for the first slash '/' outside of a string
|
||||
*/
|
||||
inq = 0 ;
|
||||
while (i<FITSLINESZ) {
|
||||
if (line[i]=='\'')
|
||||
inq=!inq ;
|
||||
if (line[i]=='/')
|
||||
if (!inq)
|
||||
break ;
|
||||
i++;
|
||||
}
|
||||
i-- ;
|
||||
/* Backtrack on blanks */
|
||||
while (line[i]==' ' && i>=0) i-- ;
|
||||
if (i<0) {
|
||||
return NULL ;
|
||||
}
|
||||
to=i ;
|
||||
if (to<from) {
|
||||
return NULL ;
|
||||
}
|
||||
/* Copy relevant characters into output buffer */
|
||||
strncpy(value, line+from, to-from+1);
|
||||
/* Null-terminate the string */
|
||||
value[to-from+1] = (char)0;
|
||||
/*
|
||||
* Make it pretty: remove head and tail quote, change double
|
||||
* quotes to simple ones.
|
||||
*/
|
||||
strcpy(value, fits_pretty_string(value));
|
||||
return value ;
|
||||
}
|
||||
|
||||
|
||||
/* Replace the MD5 card in the input header */
|
||||
static int fits_replace_card(char * filename, int off_md5, char * datamd5)
|
||||
{
|
||||
char * buf ;
|
||||
int fd ;
|
||||
struct stat sta ;
|
||||
char card[FITSLINESZ];
|
||||
int i ;
|
||||
int err ;
|
||||
|
||||
/* Get file size */
|
||||
if (stat(filename, &sta)==-1) {
|
||||
fprintf(stderr, "%s: cannot stat file [%s]: no update done\n",
|
||||
pname,
|
||||
filename);
|
||||
return 1 ;
|
||||
}
|
||||
/* Open file */
|
||||
fd = open(filename, O_RDWR);
|
||||
if (fd==-1) {
|
||||
fprintf(stderr,
|
||||
"%s: cannot open file [%s] for modification: no update done\n",
|
||||
pname,
|
||||
filename);
|
||||
return 1 ;
|
||||
}
|
||||
/* Memory-map the file */
|
||||
buf = (char*)mmap(0,
|
||||
sta.st_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
fd,
|
||||
0);
|
||||
if (buf==(char*)-1 || buf==NULL) {
|
||||
perror("mmap");
|
||||
close(fd);
|
||||
return 1 ;
|
||||
}
|
||||
/* sprintf should be safe, the MD5 signature size is 32 chars */
|
||||
sprintf(card, "%s= '%s' / data MD5 signature", FITSMD5KEY, datamd5);
|
||||
i=FITSLINESZ-1 ;
|
||||
while (card[i]!='e') {
|
||||
card[i]=' ';
|
||||
i-- ;
|
||||
}
|
||||
/* Copy card into file */
|
||||
memcpy(buf+off_md5, card, FITSLINESZ);
|
||||
/* flush output, unmap buffer, close file and quit */
|
||||
err=0 ;
|
||||
sync();
|
||||
if (close(fd)==-1) {
|
||||
fprintf(stderr, "%s: error closing modified file [%s]",
|
||||
pname,
|
||||
filename);
|
||||
err++ ;
|
||||
}
|
||||
if (munmap(buf, sta.st_size)==-1) {
|
||||
perror("munmap");
|
||||
err++ ;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Display or modify the DATAMD5 value. Returns the number of errors. */
|
||||
static int fits_md5_check(char * filename, int update_header)
|
||||
{
|
||||
FILE * in ;
|
||||
char buf[FITSBLOCKSZ];
|
||||
char * buf_c ;
|
||||
int i ;
|
||||
int in_header ;
|
||||
char * hdrmd5 ;
|
||||
struct MD5Context ctx ;
|
||||
unsigned char digest[16] ;
|
||||
static char datamd5[MD5HASHSZ+1];
|
||||
int off_md5 ;
|
||||
int cur_off ;
|
||||
int md5keysz ;
|
||||
int err ;
|
||||
int check_fits ;
|
||||
struct stat sta ;
|
||||
|
||||
if (filename==NULL) return 1 ;
|
||||
|
||||
/* Try to stat file */
|
||||
if (stat(filename, &sta)!=0) {
|
||||
fprintf(stderr, "%s: cannot stat file %s\n", pname, filename);
|
||||
return 1 ;
|
||||
}
|
||||
/* See if this is a regular file */
|
||||
if (!S_ISREG(sta.st_mode)) {
|
||||
fprintf(stderr, "%s: not a regular file: %s\n", pname, filename);
|
||||
return 1 ;
|
||||
}
|
||||
/* Open input file */
|
||||
if ((in=fopen(filename, "r"))==NULL) {
|
||||
fprintf(stderr, "%s: cannot open file [%s]\n", pname, filename);
|
||||
return 1 ;
|
||||
}
|
||||
/* Initialize all variables */
|
||||
MD5Init(&ctx);
|
||||
in_header=1 ;
|
||||
hdrmd5=NULL ;
|
||||
off_md5=0;
|
||||
cur_off=0;
|
||||
md5keysz = (int)strlen(FITSMD5KEY) ;
|
||||
check_fits=0 ;
|
||||
/* Loop over input file */
|
||||
while (fread(buf, 1, FITSBLOCKSZ, in)==FITSBLOCKSZ) {
|
||||
/* First time in the loop: check the file is FITS */
|
||||
if (check_fits==0) {
|
||||
/* Examine first characters in block */
|
||||
if (buf[0]!='S' ||
|
||||
buf[1]!='I' ||
|
||||
buf[2]!='M' ||
|
||||
buf[3]!='P' ||
|
||||
buf[4]!='L' ||
|
||||
buf[5]!='E' ||
|
||||
buf[6]!=' ' ||
|
||||
buf[7]!=' ' ||
|
||||
buf[8]!='=') {
|
||||
fprintf(stderr, "%s: file [%s] is not FITS\n",
|
||||
pname,
|
||||
filename);
|
||||
fclose(in);
|
||||
return 1 ;
|
||||
} else {
|
||||
check_fits=1 ;
|
||||
}
|
||||
}
|
||||
/* If current block is a header block */
|
||||
if (in_header) {
|
||||
buf_c = buf ;
|
||||
for (i=0 ; i<FITSCARDS ; i++) {
|
||||
/* Try to locate MD5 keyword if not located already */
|
||||
if (hdrmd5==NULL) {
|
||||
if (!strncmp(buf_c, FITSMD5KEY, md5keysz)) {
|
||||
hdrmd5 = fits_getvalue(buf_c) ;
|
||||
off_md5 = cur_off ;
|
||||
}
|
||||
}
|
||||
/* Try to locate an END key */
|
||||
if (buf_c[0]=='E' &&
|
||||
buf_c[1]=='N' &&
|
||||
buf_c[2]=='D' &&
|
||||
buf_c[3]==' ') {
|
||||
in_header=0 ;
|
||||
break ;
|
||||
}
|
||||
buf_c += FITSLINESZ ;
|
||||
cur_off += FITSLINESZ ;
|
||||
}
|
||||
} else {
|
||||
/* If current block is a data block */
|
||||
/* Try to locate an extension header */
|
||||
if (buf[0]=='X' &&
|
||||
buf[1]=='T' &&
|
||||
buf[2]=='E' &&
|
||||
buf[3]=='N' &&
|
||||
buf[4]=='S' &&
|
||||
buf[5]=='I' &&
|
||||
buf[6]=='O' &&
|
||||
buf[7]=='N' &&
|
||||
buf[8]=='=') {
|
||||
in_header=1 ;
|
||||
buf_c = buf ;
|
||||
for (i=0 ; i<FITSCARDS ; i++) {
|
||||
/* Try to find an END marker in this block */
|
||||
if (buf_c[0]=='E' &&
|
||||
buf_c[1]=='N' &&
|
||||
buf_c[2]=='D' &&
|
||||
buf_c[3]==' ') {
|
||||
/* Found END marker in same block as XTENSION */
|
||||
in_header=0 ;
|
||||
break ;
|
||||
}
|
||||
buf_c += FITSLINESZ ;
|
||||
}
|
||||
} else {
|
||||
/* Data block: accumulate for MD5 */
|
||||
MD5Update(&ctx, (unsigned char *)buf, FITSBLOCKSZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(in);
|
||||
if (check_fits==0) {
|
||||
/* Never went through the read loop: file is not FITS */
|
||||
fprintf(stderr, "%s: file [%s] is not FITS\n",
|
||||
pname,
|
||||
filename);
|
||||
return 1 ;
|
||||
}
|
||||
/* Got to the end of file: summarize */
|
||||
MD5Final(digest, &ctx);
|
||||
|
||||
/* Write digest into a string */
|
||||
sprintf(datamd5,
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
digest[ 0], digest[ 1], digest[ 2], digest[ 3], digest[ 4],
|
||||
digest[ 5], digest[ 6], digest[ 7], digest[ 8], digest[ 9],
|
||||
digest[10], digest[11], digest[12], digest[13], digest[14],
|
||||
digest[15]);
|
||||
if (!silent_process) {
|
||||
printf("filename : %s\n"
|
||||
"MD5 declared: %s\n"
|
||||
"MD5 computed: %s\n",
|
||||
filename,
|
||||
hdrmd5 ? hdrmd5 : "none",
|
||||
datamd5);
|
||||
}
|
||||
/* Update header if requested */
|
||||
err=0 ;
|
||||
if (update_header) {
|
||||
if (hdrmd5==NULL) {
|
||||
fprintf(stderr, "%s: cannot update header: missing %s\n",
|
||||
pname,
|
||||
FITSMD5KEY);
|
||||
return 1 ;
|
||||
}
|
||||
err = fits_replace_card(filename, off_md5, datamd5);
|
||||
}
|
||||
return err ;
|
||||
}
|
||||
|
||||
|
||||
/* Compute MD5 sum on the whole file and print out results on stdout */
|
||||
static int compute_md5(char * filename)
|
||||
{
|
||||
struct MD5Context ctx ;
|
||||
unsigned char digest[16] ;
|
||||
struct stat sta ;
|
||||
int fd ;
|
||||
unsigned char * buf ;
|
||||
|
||||
/* Try to stat file */
|
||||
if (stat(filename, &sta)!=0) {
|
||||
fprintf(stderr, "%s: cannot stat file %s\n", pname, filename);
|
||||
return 1 ;
|
||||
}
|
||||
/* See if this is a regular file */
|
||||
if (!S_ISREG(sta.st_mode)) {
|
||||
fprintf(stderr, "%s: not a regular file: %s\n", pname, filename);
|
||||
return 1 ;
|
||||
}
|
||||
/* Open file */
|
||||
if ((fd = open(filename, O_RDONLY))==-1) {
|
||||
fprintf(stderr, "%s: cannot open file %s\n", pname, filename);
|
||||
return 1 ;
|
||||
}
|
||||
/* Memory-map the file */
|
||||
buf = (unsigned char*)mmap(0, sta.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (buf==(unsigned char*)-1 || buf==NULL) {
|
||||
perror("mmap");
|
||||
close(fd);
|
||||
return 1 ;
|
||||
}
|
||||
/* Initialize MD5 context */
|
||||
MD5Init(&ctx);
|
||||
/* Compute MD5 on all bits in the file */
|
||||
MD5Update(&ctx, buf, sta.st_size);
|
||||
/* Finalize and print results */
|
||||
close(fd);
|
||||
munmap((char*)buf, sta.st_size);
|
||||
MD5Final(digest, &ctx);
|
||||
printf(
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x %s\n",
|
||||
digest[ 0], digest[ 1], digest[ 2], digest[ 3], digest[ 4],
|
||||
digest[ 5], digest[ 6], digest[ 7], digest[ 8], digest[ 9],
|
||||
digest[10], digest[11], digest[12], digest[13], digest[14],
|
||||
digest[15],
|
||||
filename);
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
/* This function only gives the usage for the program */
|
||||
static void usage(void)
|
||||
{
|
||||
printf(
|
||||
"%s -- %s\n"
|
||||
"version: $Revision: 1.1 $\n",
|
||||
pname,
|
||||
prog_desc);
|
||||
printf(
|
||||
"\n"
|
||||
"use : %s [-u] [-s] [-a] <FITS files...>\n"
|
||||
"options are:\n"
|
||||
"\t-u update MD5 keyword in the file: %s\n"
|
||||
"\t-s silent mode\n"
|
||||
"\n"
|
||||
"\t-a compute MD5 sum of the complete file (incl.header)\n"
|
||||
"\n"
|
||||
"This utility computes the MD5 checksum of all data sections\n"
|
||||
"in a given FITS file, and compares it against the value\n"
|
||||
"declared in DATAMD5 if present. It can also update the value\n"
|
||||
"of this keyword (if present) with its own computed MD5 sum.\n"
|
||||
"\n"
|
||||
"You can also use it with the -a option to compute the MD5 sum\n"
|
||||
"on the complete file (all bits). In this case, the file needs\n"
|
||||
"not be FITS. This option is only provided to check this program\n"
|
||||
"against other MD5 computation tools.\n"
|
||||
"NB: Other options cannot be used together with -a.\n"
|
||||
"\n",
|
||||
pname,
|
||||
FITSMD5KEY);
|
||||
exit(0) ;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Main code
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i ;
|
||||
int update_header ;
|
||||
int total_md5 ;
|
||||
int err ;
|
||||
|
||||
pname=argv[0];
|
||||
update_header = 0 ;
|
||||
total_md5 = 0 ;
|
||||
if (argc<2) {
|
||||
usage();
|
||||
}
|
||||
/* Parse arguments for options */
|
||||
for (i=1 ; i<argc ; i++) {
|
||||
if (!strcmp(argv[i], "-u")) {
|
||||
update_header=1 ;
|
||||
} else if (!strcmp(argv[i], "-s")) {
|
||||
silent_process=1;
|
||||
} else if (!strcmp(argv[i], "-a")) {
|
||||
total_md5=1 ;
|
||||
}
|
||||
}
|
||||
/* Loop on input file names */
|
||||
err=0 ;
|
||||
for (i=1 ; i<argc ; i++) {
|
||||
/* If not a command-line option */
|
||||
if (strcmp(argv[i], "-u") &&
|
||||
strcmp(argv[i], "-s") &&
|
||||
strcmp(argv[i], "-a")) {
|
||||
/* Launch MD5 process on this file */
|
||||
if (total_md5) {
|
||||
err+=compute_md5(argv[i]);
|
||||
} else {
|
||||
err += fits_md5_check(argv[i], update_header);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (err>0) {
|
||||
fprintf(stderr, "%s: %d error(s) during process\n", pname, err);
|
||||
}
|
||||
return err ;
|
||||
}
|
|
@ -0,0 +1,448 @@
|
|||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
||||
File name : fitsort.c
|
||||
Author : Nicolas Devillard
|
||||
Created on : May 1st, 1996
|
||||
Description : Sorts out FITS keywords.
|
||||
The input is a succession of FITS headers delivered
|
||||
through stdin by 'dfits'. On the command line, specify
|
||||
which keywords you wish to display, the output contains
|
||||
for each file, the file name and the keyword values
|
||||
in column format.
|
||||
Example:
|
||||
dfits *.fits | fitsort BITPIX NAXIS NAXIS1 NAXIS2 NAXIS3
|
||||
The output would be like:
|
||||
|
||||
File BITPIX NAXIS NAXIS1 NAXIS2 NAXIS3
|
||||
|
||||
image1.fits 32 2 256 256
|
||||
image2.fits -32 3 128 128 40
|
||||
...
|
||||
|
||||
Using 'fitsort -d ...' would prevent printing the
|
||||
first line (filename and keyword names).
|
||||
|
||||
The output format is simple: values are separated by
|
||||
tabs, records by linefeeds. When no value is present
|
||||
(no keyword in this header), only a tab is printed
|
||||
out.
|
||||
|
||||
Example:
|
||||
file1.fits contains NAXIS1=100 NAXIS2=200
|
||||
file2.fits contains NAXIS1=20
|
||||
|
||||
dfits file1.fits file2.fits | fitsort NAXIS2 NAXIS1
|
||||
would litterally print out (\t stands for tab, \n for linefeed):
|
||||
|
||||
file1.fits\t200\t100\n
|
||||
file2.fits\t\t20\n
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: fitsort.c,v 1.1 2001/12/14 09:15:19 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2001/12/14 09:15:19 $
|
||||
$Revision: 1.1 $
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define MAX_STRING 128 /* Maximum string length */
|
||||
#define MAX_KEY 512 /* Maximum number of keywords to search for */
|
||||
|
||||
#define FMT_STRING "%%-%ds\t"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
New types
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* This holds a keyword value and a flag to indicate its presence */
|
||||
|
||||
typedef struct _KEYWORD_ {
|
||||
char value[MAX_STRING] ;
|
||||
int present ;
|
||||
} keyword ;
|
||||
|
||||
/*
|
||||
* Each detected file in input has such an associated structure, which
|
||||
* contains the file name and a list of associated keywords.
|
||||
*/
|
||||
|
||||
typedef struct _RECORD_ {
|
||||
char filename[MAX_STRING] ;
|
||||
keyword listkw[MAX_KEY] ;
|
||||
} record ;
|
||||
|
||||
/*
|
||||
* NB: Everything is deliberately allocated statically. As we are not
|
||||
* dealing with huge amounts of data, works fine and makes it easier to
|
||||
* read/write/modify.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
See function descriptions below
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
isfilename(char *string) ;
|
||||
|
||||
static void
|
||||
getfilename(char *line, char *word) ;
|
||||
|
||||
static char *
|
||||
expand_hierarch_keyword(
|
||||
char * dotkey,
|
||||
char * hierarchy
|
||||
);
|
||||
|
||||
static int
|
||||
isdetectedkeyword(char *line, char *keywords[], int nkeys) ;
|
||||
|
||||
static void
|
||||
getkeywordvalue(char *line, char *word) ;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char curline[MAX_STRING] ;
|
||||
char word[MAX_STRING] ;
|
||||
int i, j ;
|
||||
int nfiles ;
|
||||
record *allrecords ;
|
||||
int kwnum ;
|
||||
int len ;
|
||||
int max_width[MAX_KEY] ;
|
||||
int max_filnam ;
|
||||
char fmt[8] ;
|
||||
int flag ;
|
||||
int printnames ;
|
||||
int print_hdr ;
|
||||
|
||||
if (argc<2) {
|
||||
printf("\n\nuse : %s [-d] KEY1 KEY2 ... KEYn\n", argv[0]) ;
|
||||
printf("Input data is received from stdin\n") ;
|
||||
printf("See man page for more details and examples\n\n") ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
printnames = 0 ;
|
||||
print_hdr = 1 ;
|
||||
nfiles = 0 ;
|
||||
allrecords = (record*)calloc(1, sizeof(record));
|
||||
if (!strcmp(argv[1], "-d")) {
|
||||
print_hdr = 0;
|
||||
argv++ ;
|
||||
argc-- ;
|
||||
}
|
||||
argv++ ;
|
||||
|
||||
/* Uppercase all inputs */
|
||||
for (i=0 ; i<(argc-1) ; i++) {
|
||||
j=0 ;
|
||||
while (argv[i][j]!=0) {
|
||||
argv[i][j] = toupper(argv[i][j]);
|
||||
j++ ;
|
||||
}
|
||||
}
|
||||
|
||||
while (fgets(curline, MAX_STRING, stdin) != (char*)NULL) {
|
||||
if ((flag=isfilename(curline))!=0) {
|
||||
/* New file entry is detected */
|
||||
if (flag==1) {
|
||||
/* New file name is detected, get the new file name */
|
||||
printnames = 1 ;
|
||||
getfilename(curline, allrecords[nfiles].filename) ;
|
||||
/* Absorb next line (contains SIMPLE=) */
|
||||
fgets(curline, MAX_STRING, stdin);
|
||||
} else {
|
||||
/* New SIMPLE=T entry, no associated file name */
|
||||
allrecords[nfiles].filename[0] = (char)0;
|
||||
}
|
||||
nfiles++ ;
|
||||
/*
|
||||
* Initialize a new record structure to store input data for
|
||||
* this file.
|
||||
*/
|
||||
|
||||
allrecords = (record*)realloc( allrecords,
|
||||
(nfiles+1)*sizeof(record)) ;
|
||||
for (i=0 ; i<MAX_KEY ; i++)
|
||||
allrecords[nfiles].listkw[i].present = 0 ;
|
||||
} else {
|
||||
/* Is not a file name, is it a searched keyword? */
|
||||
if ((kwnum = isdetectedkeyword( curline,
|
||||
argv,
|
||||
argc-1)) != -1) {
|
||||
/* Is there anything allocated yet to store this? */
|
||||
if (nfiles>0) {
|
||||
/* It has been detected as a searched keyword. */
|
||||
/* Get its value, store it, present flag up */
|
||||
getkeywordvalue(curline, word) ;
|
||||
strcpy(allrecords[nfiles-1].listkw[kwnum].value, word) ;
|
||||
allrecords[nfiles-1].listkw[kwnum].present ++ ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i=0 ; i<argc-1 ; i++) {
|
||||
max_width[i] = (int)strlen(argv[i]) ;
|
||||
}
|
||||
|
||||
/* Record the maximum width for each column */
|
||||
max_filnam = 0 ;
|
||||
for (i=0 ; i<nfiles ; i++) {
|
||||
len = (int)strlen(allrecords[i].filename) ;
|
||||
if (len>max_filnam) max_filnam=len ;
|
||||
for (kwnum=0 ; kwnum<argc-1 ; kwnum++) {
|
||||
if (allrecords[i].listkw[kwnum].present) {
|
||||
len = (int)strlen(allrecords[i].listkw[kwnum].value) ;
|
||||
} else {
|
||||
len = 0 ;
|
||||
}
|
||||
if (len>max_width[kwnum])
|
||||
max_width[kwnum] = len ;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print out header line */
|
||||
if (print_hdr) {
|
||||
sprintf(fmt, FMT_STRING, max_filnam) ;
|
||||
if (printnames) printf(fmt, "FILE");
|
||||
for (i=0 ; i<argc-1 ; i++) {
|
||||
sprintf(fmt, FMT_STRING, max_width[i]) ;
|
||||
printf(fmt, argv[i]) ;
|
||||
}
|
||||
printf("\n") ;
|
||||
}
|
||||
|
||||
|
||||
/* Now print out stored data */
|
||||
if (nfiles<1) {
|
||||
printf("*** error: no input data corresponding to dfits output\n");
|
||||
return -1 ;
|
||||
}
|
||||
for (i=0 ; i<nfiles ; i++) {
|
||||
if (printnames) {
|
||||
sprintf(fmt, FMT_STRING, max_filnam) ;
|
||||
printf(fmt, allrecords[i].filename) ;
|
||||
}
|
||||
for (kwnum=0 ; kwnum<argc-1 ; kwnum++) {
|
||||
sprintf(fmt, FMT_STRING, max_width[kwnum]);
|
||||
if (allrecords[i].listkw[kwnum].present)
|
||||
printf(fmt, allrecords[i].listkw[kwnum].value) ;
|
||||
else
|
||||
printf(fmt, " ");
|
||||
}
|
||||
printf("\n") ;
|
||||
}
|
||||
free(allrecords) ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Function : isfilename()
|
||||
In : dfits output line
|
||||
Out : integer
|
||||
1 if the line contains a valid file name as produced
|
||||
by dfits.
|
||||
2 if the line starts with 'SIMPLE ='
|
||||
0 else
|
||||
Job : find out if an input line contains a file name or a
|
||||
FITS magic number
|
||||
Notice :
|
||||
Filename recognition is based on 'dfits' output.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
isfilename(char *string)
|
||||
{
|
||||
if (!strncmp(string, "====>", 5)) return 1 ;
|
||||
if (!strncmp(string, "SIMPLE =", 9)) return 2 ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Function : getfilename()
|
||||
In : dfits output line
|
||||
Out : second argument: file name
|
||||
Job : returns a file name from a dfits output line
|
||||
Notice : This is dfits dependent.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
getfilename(char *line, char *word)
|
||||
{
|
||||
/* get filename from a dfits output */
|
||||
sscanf(line, "%*s %*s %s", word) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Function : isdetectedkeyword()
|
||||
In : FITS line, set of keywords, number of kw in the set.
|
||||
Out : keyword rank, -1 if unidentified
|
||||
Job : detects a if a keyword is present in a FITS line.
|
||||
Notice :
|
||||
Feed this function a FITS line, a set of keywords in the
|
||||
*argv[] fashion (*keywords[]).
|
||||
If the provided line appears to contain one of the keywords
|
||||
registered in the list, the rank of the keyword in the list
|
||||
is returned, otherwise, -1 is returned.
|
||||
---------------------------------------------------------------------------*/
|
||||
static int
|
||||
isdetectedkeyword( char *line,
|
||||
char *keywords[],
|
||||
int nkeys)
|
||||
{
|
||||
int i ;
|
||||
char kw[MAX_STRING] ;
|
||||
char esokw[MAX_STRING] ;
|
||||
|
||||
/*
|
||||
* The keywors is defined as the input line, up to the equal character,
|
||||
* with trailing blanks removed
|
||||
*/
|
||||
strcpy(kw, line) ;
|
||||
strtok(kw, "=") ;
|
||||
/* Now remove all trailing blanks (if any) */
|
||||
i = (int)strlen(kw) -1 ;
|
||||
while (kw[i] == ' ') i -- ;
|
||||
kw[i+1] = (char)0 ;
|
||||
|
||||
/* Now compare what we got with what's available */
|
||||
for (i=0 ; i<nkeys ; i++) {
|
||||
if (strstr(keywords[i], ".")!=NULL) {
|
||||
/*
|
||||
* keyword contains a dot, it is a hierarchical keyword that
|
||||
* must be expanded. Pattern is:
|
||||
* A.B.C... becomes HIERARCH ESO A B C ...
|
||||
*/
|
||||
expand_hierarch_keyword(keywords[i], esokw) ;
|
||||
if (!strcmp(kw, esokw)) {
|
||||
return i ;
|
||||
}
|
||||
} else if (!strcmp(kw, keywords[i])) {
|
||||
return i ;
|
||||
}
|
||||
}
|
||||
/* Keyword not found */
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function : expand_hierarch_keyword()
|
||||
In : two allocated strings
|
||||
Out : char *, pointer to second input string (modified)
|
||||
Job : from a HIERARCH keyword in format A.B.C expand to
|
||||
HIERARCH ESO A B C
|
||||
Notice :
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static char *
|
||||
expand_hierarch_keyword(
|
||||
char * dotkey,
|
||||
char * hierarchy
|
||||
)
|
||||
{
|
||||
char * token ;
|
||||
char ws[MAX_STRING] ;
|
||||
|
||||
sprintf(hierarchy, "HIERARCH ESO");
|
||||
strcpy(ws, dotkey) ;
|
||||
token = strtok(ws, ".") ;
|
||||
while (token!=NULL) {
|
||||
strcat(hierarchy, " ") ;
|
||||
strcat(hierarchy, token) ;
|
||||
token = strtok(NULL, ".");
|
||||
}
|
||||
return hierarchy ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Function : getkeywordvalue()
|
||||
In : FITS line to process, char string to return result
|
||||
Out : void, result returned in char *word
|
||||
Job : Get a keyword value within a FITS line
|
||||
Notice : No complex value is recognized
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
getkeywordvalue(char *line, char *word)
|
||||
{
|
||||
int c, w ;
|
||||
char tmp[MAX_STRING] ;
|
||||
char *begin, *end ;
|
||||
int length ;
|
||||
int quote = 0 ;
|
||||
int search = 1 ;
|
||||
|
||||
memset(tmp, (char)0, MAX_STRING) ;
|
||||
memset(word, (char)0, MAX_STRING) ;
|
||||
c = w = 0;
|
||||
|
||||
/* Parse the line till the equal '=' sign is found */
|
||||
|
||||
while (line[c] != '=') c++ ;
|
||||
c++ ;
|
||||
|
||||
/* Copy the line till the slash '/' sign is found */
|
||||
/* or the end of data is found. */
|
||||
|
||||
while (search == 1) {
|
||||
|
||||
if (c>=80) {
|
||||
search = 0 ;
|
||||
} else if ((line[c] == '/') && (quote == 0)) {
|
||||
search = 0 ;
|
||||
}
|
||||
|
||||
if (line[c] == '\'') {
|
||||
quote = !quote ;
|
||||
}
|
||||
|
||||
tmp[w++] = line[c++] ;
|
||||
}
|
||||
|
||||
/* NULL termination of the string */
|
||||
tmp[--w] = (char)0 ;
|
||||
|
||||
/* Return the keyword only : a difference is made between text fields */
|
||||
/* and numbers. */
|
||||
|
||||
if ((begin = strchr(tmp, '\'')) != (char*)NULL) {
|
||||
/* A quote has been found: it is a string value */
|
||||
begin++ ;
|
||||
end = strrchr(tmp, '\'') ;
|
||||
length = (int)strlen(begin) - (int)strlen(end) ;
|
||||
strncpy(word, begin, length) ;
|
||||
} else {
|
||||
/* No quote, just get the value (only one, no complex supported) */
|
||||
sscanf(tmp, "%s", word) ;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
|
@ -0,0 +1,664 @@
|
|||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
||||
File name : hierarch28.c
|
||||
Author : N. Devillard
|
||||
Created on : July 14th, 1998
|
||||
Description : header conversion from ESO-FITS to standard FITS
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: hierarch28.c,v 1.1 2001/12/14 09:15:19 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2001/12/14 09:15:19 $
|
||||
$Revision: 1.1 $
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#define NM_SIZ 512
|
||||
#define FITS_LINE 80
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Private functions and module variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static char prog_desc[] = "header conversion from ESO to standard FITS" ;
|
||||
|
||||
static void usage(char *) ;
|
||||
static int convert_eso_to_std_FITS(char *, char *) ;
|
||||
static void free_keys(char **, int n) ;
|
||||
static void strip_beg_end(char *) ;
|
||||
static int
|
||||
search_and_replace_kw(
|
||||
char * buf,
|
||||
int bufsize,
|
||||
char ** key_in,
|
||||
char ** key_out,
|
||||
int nk
|
||||
);
|
||||
static void search_rep(char *, char *, char *);
|
||||
|
||||
static void generate_default_convtab(void);
|
||||
static char * convert_deg_to_str( double deg ) ;
|
||||
|
||||
static char CONVTAB_DEFAULT[] =
|
||||
"#\n"
|
||||
"# Example of conversion table for hierarch28\n"
|
||||
"#\n"
|
||||
"# A note about this file's format:\n"
|
||||
"# Any blank line or line starting with a hash is ignored.\n"
|
||||
"# Declare the keyword names to search and replace with:\n"
|
||||
"#\n"
|
||||
"# OLDKEYWORD1 = NEWKEYWORD1\n"
|
||||
"# OLDKEYWORD2 = NEWKEYWORD2\n"
|
||||
"# etc.\n"
|
||||
"#\n"
|
||||
"# Spaces are allowed within keyword names, to allow e.g.:\n"
|
||||
"#\n"
|
||||
"# HIERARCH ESO DET DIT = DETDIT\n"
|
||||
"# HIERARCH ESO DET NDIT = DET NDIT\n"
|
||||
"# HIERARCH ESO DET NINT = HIERARCH ESO NINT\n"
|
||||
"#\n"
|
||||
"# The most important restriction is that new keywords shall not be\n"
|
||||
"# longer than the keywords they replace.\n"
|
||||
"#\n"
|
||||
"#\n"
|
||||
"# Translation table for basic keywords used by IRAF\n"
|
||||
"# -------------------------------------------------\n"
|
||||
"#\n"
|
||||
"# Note: hierarch28 will replace keywords in the main header\n"
|
||||
"# and also in extensions.\n"
|
||||
"#\n"
|
||||
"# Disclaimer:\n"
|
||||
"# this table has been compiled to best knowledge of present\n"
|
||||
"# IRAF packages. Please let us know of any addition/change.\n"
|
||||
"#\n"
|
||||
"\n"
|
||||
"UTC = UT\n"
|
||||
"LST = ST\n"
|
||||
"RA = RA\n"
|
||||
"DEC = DEC\n"
|
||||
"\n"
|
||||
"HIERARCH ESO TEL AIRM START = AIRMASS\n"
|
||||
"HIERARCH ESO DPR TYPE = IMAGETYP\n"
|
||||
"HIERARCH ESO INS FILT1 NAME = FILTER1\n"
|
||||
"HIERARCH ESO INS FILT2 NAME = FILTER2\n"
|
||||
"HIERARCH ESO INS FILT3 NAME = FILTER3\n"
|
||||
"HIERARCH ESO INS FILT4 NAME = FILTER4\n"
|
||||
"HIERARCH ESO INS SLIT2 NAME = SLIT\n"
|
||||
"HIERARCH ESO INS GRIS1 NAME = GRISM\n"
|
||||
"HIERARCH ESO INS GRAT NAME = GRAT\n"
|
||||
"HIERARCH ESO INS GRAT1 NAME = GRAT1\n"
|
||||
"HIERARCH ESO INS GRAT2 NAME = GRAT2\n"
|
||||
"HIERARCH ESO INS GRAT WLEN = WLEN\n"
|
||||
"HIERARCH ESO INS GRAT1 WLEN = WLEN1\n"
|
||||
"HIERARCH ESO INS GRAT2 WLEN = WLEN2\n"
|
||||
"HIERARCH ESO INS GRAT ORDER = ORDER\n"
|
||||
"\n"
|
||||
"#\n"
|
||||
"# A note for IRAF users:\n"
|
||||
"# hierarch28 performs a translation to the IRAF convention on the\n"
|
||||
"# following four keywords 'RA', 'DEC', 'UT' and 'ST'. IRAF requires\n"
|
||||
"# these keywords to contain the string representation of their values.\n"
|
||||
"#\n"
|
||||
"# Be aware also that the ESO convention names the keywords UTC and\n"
|
||||
"# LST, whereas the IRAF convention is 'UT' and 'ST'.\n"
|
||||
"#\n"
|
||||
"# e.g.\n"
|
||||
"#\n"
|
||||
"# RA = ' 09:45:14.594' / RA (J2000) pointing\n"
|
||||
"# DEC = '-33:47:09.420' / DEC (J2000) pointing\n"
|
||||
"# UT = ' 01:17:21.950' / UT at start\n"
|
||||
"# ST = ' 08:19:59.688' / ST at start\n"
|
||||
"#\n"
|
||||
"# The ESO standard (see http://archive.eso.org/dicb) defines these\n"
|
||||
"# keywords as floating point values with the units degrees for RA/DEC\n"
|
||||
"# and elapsed seconds since midnight for UT/ST.\n"
|
||||
"#\n"
|
||||
"# In order to have this tranlation performed, add\n"
|
||||
"#\n"
|
||||
"# RA = RA\n"
|
||||
"# DEC = DEC\n"
|
||||
"# UTC = UT\n"
|
||||
"# LST = ST\n"
|
||||
"#\n"
|
||||
"# to the conversion table.\n"
|
||||
"#\n";
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
main()
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char name_conv[NM_SIZ] ;
|
||||
char name_in[NM_SIZ] ;
|
||||
|
||||
if (argc<2) usage(argv[0]) ;
|
||||
if (!strcmp(argv[1], "-g")) {
|
||||
generate_default_convtab() ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
strcpy(name_in, argv[1]) ;
|
||||
if (argc==3) {
|
||||
strcpy(name_conv, argv[2]) ;
|
||||
} else {
|
||||
strcpy(name_conv, "table.conv") ;
|
||||
}
|
||||
|
||||
if (convert_eso_to_std_FITS(name_in, name_conv) != 0) {
|
||||
fprintf(stderr, "error during conversion: aborting\n") ;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function only gives the usage for the program
|
||||
*/
|
||||
|
||||
static void usage(char *pname)
|
||||
{
|
||||
printf(
|
||||
"\n\n"
|
||||
"hierarch28 (hierarch-to-eight)\n"
|
||||
"%s : %s\n"
|
||||
"use : %s [options] <in> [table]\n"
|
||||
"options are:\n"
|
||||
"\t-g generates a generic table\n"
|
||||
"\n"
|
||||
"default conversion table name is 'table.conv'\n"
|
||||
"\n"
|
||||
"More help can be found in the comments included in\n"
|
||||
"the default conversion table. Generate one with\n"
|
||||
"the -g option and read it.\n"
|
||||
"\n\n",
|
||||
pname, prog_desc, pname);
|
||||
exit(0) ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name convert_eso_to_std_FITS
|
||||
@memo Search and replace FITS keywords in main/extension headers.
|
||||
@param name_in File to modify.
|
||||
@param name_conv Conversion table name.
|
||||
@return int 0 if Ok, non-zero if error occurred.
|
||||
@doc
|
||||
|
||||
The input file is modified in place. Keyword names are replaced
|
||||
according to the input conversion table. In some special cases, the
|
||||
keyword values are also modified to follow the IRAF convention.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static int convert_eso_to_std_FITS(char * name_in, char * name_conv)
|
||||
{
|
||||
FILE * convtab ;
|
||||
int nkeys ;
|
||||
int i ;
|
||||
char ** key_in ;
|
||||
char ** key_out ;
|
||||
int fd ;
|
||||
char * buf ;
|
||||
char line[NM_SIZ] ;
|
||||
char kw1[FITS_LINE],
|
||||
kw2[FITS_LINE] ;
|
||||
int lineno ;
|
||||
int fs ;
|
||||
struct
|
||||
stat fileinfo ;
|
||||
|
||||
/*
|
||||
* Read conversion table and translate it to key_in, key_out
|
||||
*/
|
||||
if ((convtab = fopen(name_conv, "r")) == NULL) {
|
||||
fprintf(stderr, "cannot open conversion table: %s\n", name_conv) ;
|
||||
return -1 ;
|
||||
}
|
||||
/*
|
||||
* First, count how many keywords we need to translate
|
||||
*/
|
||||
nkeys = 0 ;
|
||||
while (fgets(line, FITS_LINE, convtab)!=NULL) {
|
||||
if ((line[0] != '#') && (line[0] != '\n')) {
|
||||
nkeys ++ ;
|
||||
}
|
||||
}
|
||||
rewind(convtab) ;
|
||||
|
||||
/*
|
||||
* Allocate space to store keyword info
|
||||
*/
|
||||
key_in = malloc(nkeys * sizeof(char*)) ;
|
||||
key_out = malloc(nkeys * sizeof(char*)) ;
|
||||
|
||||
/*
|
||||
* Now read the file through and get the keywords
|
||||
*/
|
||||
i = 0 ;
|
||||
lineno = 0 ;
|
||||
while (fgets(line, FITS_LINE, convtab)!=NULL) {
|
||||
lineno++ ;
|
||||
if ((line[0]!='#') && (line[0]!='\n')) {
|
||||
if (sscanf(line, "%[^=] = %[^;#]", kw1, kw2)!=2) {
|
||||
fprintf(stderr,
|
||||
"*** error parsing table file %s\n", name_conv);
|
||||
fprintf(stderr, "line: %d\n", lineno) ;
|
||||
free_keys(key_in, i) ;
|
||||
free_keys(key_out, i) ;
|
||||
fclose(convtab) ;
|
||||
return -1 ;
|
||||
}
|
||||
strip_beg_end(kw1) ;
|
||||
strip_beg_end(kw2) ;
|
||||
if (strlen(kw2)>strlen(kw1)) {
|
||||
fprintf(stderr,
|
||||
"*** error in conversion table %s (line %d)\n",
|
||||
name_conv, lineno);
|
||||
fprintf(stderr,
|
||||
"*** error: dest keyword is longer than original\n");
|
||||
fprintf(stderr, "orig: [%s] dest: [%s]\n", kw1, kw2);
|
||||
fclose(convtab) ;
|
||||
free_keys(key_in, i) ;
|
||||
free_keys(key_out, i) ;
|
||||
return -1 ;
|
||||
}
|
||||
key_in[i] = strdup(kw1) ;
|
||||
key_out[i] = strdup(kw2) ;
|
||||
i++ ;
|
||||
}
|
||||
}
|
||||
fclose(convtab) ;
|
||||
|
||||
/*
|
||||
* Print out some information about what is being done
|
||||
*/
|
||||
printf("\n\n") ;
|
||||
printf("*** hierarch28\n") ;
|
||||
printf("\n") ;
|
||||
printf("searching %s and replacing the following keywords:\n",
|
||||
name_in) ;
|
||||
for (i=0 ; i<nkeys ; i++) {
|
||||
printf("\t[%s]\t=>\t[%s]\n", key_in[i], key_out[i]) ;
|
||||
}
|
||||
printf("\n\n") ;
|
||||
|
||||
/*
|
||||
* mmap the input file entirely
|
||||
*/
|
||||
|
||||
if (stat(name_in, &fileinfo)!=0) {
|
||||
fprintf(stderr, "*** error: accessing file [%s]\n", name_in);
|
||||
free_keys(key_in, nkeys) ;
|
||||
free_keys(key_out, nkeys) ;
|
||||
return -1 ;
|
||||
}
|
||||
fs = (int)fileinfo.st_size ;
|
||||
if (fs < 1) {
|
||||
fprintf(stderr, "error getting FITS header size for %s\n", name_in);
|
||||
free_keys(key_in, nkeys) ;
|
||||
free_keys(key_out, nkeys) ;
|
||||
return -1 ;
|
||||
}
|
||||
fd = open(name_in, O_RDWR) ;
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "cannot open %s: aborting\n", name_in) ;
|
||||
free_keys(key_in, nkeys) ;
|
||||
free_keys(key_out, nkeys) ;
|
||||
return -1 ;
|
||||
}
|
||||
buf = (char*)mmap(0,
|
||||
fs,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
fd,
|
||||
0) ;
|
||||
if (buf == (char*)-1) {
|
||||
perror("mmap") ;
|
||||
fprintf(stderr, "cannot mmap file: %s\n", name_in) ;
|
||||
free_keys(key_in, nkeys) ;
|
||||
free_keys(key_out, nkeys) ;
|
||||
close(fd) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply search and replace for the input keyword lists
|
||||
*/
|
||||
if (search_and_replace_kw(buf, fs, key_in, key_out, nkeys) != 0) {
|
||||
fprintf(stderr, "error while doing search and replace\n") ;
|
||||
}
|
||||
free_keys(key_in, nkeys) ;
|
||||
free_keys(key_out, nkeys) ;
|
||||
close(fd) ;
|
||||
munmap(buf, fs) ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name strip_beg_end
|
||||
@memo Strips out blank characters off a character string.
|
||||
@param s NULL-terminated string to process.
|
||||
@return void
|
||||
@doc
|
||||
|
||||
This function removes heading and trailing blanks from a
|
||||
NULL-terminated character string. The input string is modified. The
|
||||
input string is assumed to contain only blanks or alphanumeric
|
||||
characters (like FITS keywords).
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static void strip_beg_end(char * s)
|
||||
{
|
||||
int beg, len ;
|
||||
|
||||
beg = 0 ;
|
||||
while (!isalnum(s[beg])) beg++ ;
|
||||
|
||||
len = (int)strlen(s) -1 ;
|
||||
while (!isalnum(s[len])) len -- ;
|
||||
|
||||
strncpy(s, s+beg, len-beg+1) ;
|
||||
s[len-beg+1] = (char)0 ;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name free_keys
|
||||
@memo Free memory associated to an array of keys.
|
||||
@param keyt Key table.
|
||||
@param n Number of keys in the table.
|
||||
@return void
|
||||
@doc
|
||||
|
||||
Memory was initially allocated using strdup(). This frees all the
|
||||
keys and the master table pointer.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static void free_keys(char ** keyt, int n)
|
||||
{
|
||||
int i ;
|
||||
|
||||
if (n<1) return ;
|
||||
for (i=0 ; i<n ; i++) {
|
||||
free(keyt[i]) ;
|
||||
}
|
||||
free(keyt) ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name search_and_replace_kw
|
||||
@memo Search keywords and replace them over a whole buffer.
|
||||
@param buf Buffer to modify.
|
||||
@param bufsize Buffer size in bytes.
|
||||
@param key_in Input key table.
|
||||
@param key_out Output key table.
|
||||
@param nk Number of keys in each table (same).
|
||||
@return int 0 if Ok, non-zero if error occurred.
|
||||
@doc
|
||||
|
||||
Main replace function: it browses through the entire file to support
|
||||
keyword changes in extensions too. Heavily optimized for speed.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static int search_and_replace_kw(
|
||||
char * buf,
|
||||
int bufsize,
|
||||
char ** key_in,
|
||||
char ** key_out,
|
||||
int nk
|
||||
)
|
||||
{
|
||||
char * w ;
|
||||
int i, j ;
|
||||
int in_header ;
|
||||
int match_flag ;
|
||||
int * keysizes ;
|
||||
|
||||
/* Pre-compute key sizes to gain time */
|
||||
keysizes = malloc(nk * sizeof(int));
|
||||
for (i=0 ; i<nk ; i++) {
|
||||
keysizes[i] = (int)strlen(key_in[i]);
|
||||
}
|
||||
|
||||
/* Browse through file line by line */
|
||||
w = buf ;
|
||||
in_header=1 ;
|
||||
while ((w-buf+FITS_LINE)<bufsize) {
|
||||
if (in_header) { /* Currently browsing a header */
|
||||
if (w[0]=='E' &&
|
||||
w[1]=='N' &&
|
||||
w[2]=='D' &&
|
||||
w[3]==' ') {
|
||||
/* Found an END keyword: exit from header */
|
||||
in_header=0 ;
|
||||
} else {
|
||||
/* Compare the current line with all searched keys */
|
||||
for (i=0 ; i<nk ; i++) {
|
||||
match_flag=1 ;
|
||||
for (j=0 ; j<keysizes[i] ; j++) {
|
||||
if (key_in[i][j]!=w[j]) {
|
||||
match_flag=0 ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if (match_flag) {
|
||||
search_rep(w, key_in[i], key_out[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Currently out of header, look for next extension */
|
||||
if (w[0]=='X' &&
|
||||
w[1]=='T' &&
|
||||
w[2]=='E' &&
|
||||
w[3]=='N' &&
|
||||
w[4]=='S' &&
|
||||
w[5]=='I' &&
|
||||
w[6]=='O' &&
|
||||
w[7]=='N') {
|
||||
/* Found a header start */
|
||||
in_header=1 ;
|
||||
}
|
||||
}
|
||||
w+=FITS_LINE ;
|
||||
}
|
||||
free(keysizes);
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name search_rep
|
||||
@memo Atomic keyword replacement.
|
||||
@param line Line to work on.
|
||||
@param key_i Input key.
|
||||
@param key_o Output key.
|
||||
@return void
|
||||
@doc
|
||||
|
||||
Replace in 'line' the keyword name 'key_i' by 'key_o'. In some
|
||||
special cases, the value is also modified to reflect the IRAF
|
||||
conventions.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static void search_rep(char * line, char * key_i, char * key_o)
|
||||
{
|
||||
int i, j ;
|
||||
char * equal ;
|
||||
int to_copy ;
|
||||
char * p ;
|
||||
char tmp[FITS_LINE+1];
|
||||
char comment[FITS_LINE+1];
|
||||
|
||||
equal = strstr(line, "=");
|
||||
to_copy = FITS_LINE - (equal-line);
|
||||
for (i=0 ; i<(int)strlen(key_o) ; i++) {
|
||||
line[i] = key_o[i] ;
|
||||
}
|
||||
if (strlen(key_o)<=8) {
|
||||
/* Blank-pad until equal sign is reached */
|
||||
for ( ; i<8 ; i++) {
|
||||
line[i]=' ';
|
||||
}
|
||||
/* Add equal sign */
|
||||
line[i] = '=' ;
|
||||
i++ ;
|
||||
|
||||
/* Handle special cases: the value also needs conversion */
|
||||
if(!strcmp(key_o, "RA")) {
|
||||
if (*(equal+2)!='\'') {
|
||||
/* out key is RA, translate to ' HH:MM:SS.SSS' */
|
||||
p = strchr(line+i, '/');
|
||||
if (p)
|
||||
strncpy(comment, p, line+FITS_LINE-p);
|
||||
sprintf(tmp, " %-29.29s %-40.40s",
|
||||
convert_deg_to_str(atof(equal+1)/15.),
|
||||
(p)? comment : "/ Right Ascension");
|
||||
memcpy(line+i, tmp, 71);
|
||||
}
|
||||
} else if(!strcmp(key_o, "DEC")) {
|
||||
if( *(equal+2)!='\'') {
|
||||
/* out key is DEC, translate to '+DD:MM:SS.SSS' */
|
||||
p = strchr(line+i, '/');
|
||||
if (p)
|
||||
strncpy(comment, p, line+FITS_LINE-p);
|
||||
sprintf(tmp, " %-29.29s %-40.40s",
|
||||
convert_deg_to_str(atof(equal+1)),
|
||||
(p)? comment : "/ Declination");
|
||||
memcpy(line+i, tmp, 71);
|
||||
}
|
||||
} else if(!strcmp(key_o, "UT")) {
|
||||
if( *(equal+2)!='\'') {
|
||||
/* out key is UT, translate to ' HH:MM:SS.SSS' */
|
||||
p = strchr(line+i, '/');
|
||||
if (p)
|
||||
strncpy(comment, p, line+FITS_LINE-p);
|
||||
sprintf(tmp, " %-29.29s %-40.40s",
|
||||
convert_deg_to_str(atof(equal+1)/3600.),
|
||||
(p)? comment : "/ UT");
|
||||
memcpy(line+i, tmp, 71);
|
||||
}
|
||||
} else if(!strcmp(key_o, "ST")) {
|
||||
if( *(equal+2)!='\'') {
|
||||
/* out key is ST, translate to ' HH:MM:SS.SSS' */
|
||||
p = strchr(line+i, '/');
|
||||
if (p)
|
||||
strncpy(comment, p, line+FITS_LINE-p);
|
||||
sprintf(tmp, " %-29.29s %-40.40s",
|
||||
convert_deg_to_str(atof(equal+1)/3600.),
|
||||
(p)? comment : "/ ST");
|
||||
memcpy(line+i, tmp, 71);
|
||||
}
|
||||
} else {
|
||||
/* Copy line from first char after real equal sign */
|
||||
for (j=0 ; j<to_copy ; j++) {
|
||||
line[i+j] = equal[j+1];
|
||||
}
|
||||
i+=to_copy-1 ;
|
||||
/* Blank padding */
|
||||
for ( ; i<FITS_LINE ; i++) {
|
||||
line[i]=' ';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Blank padding */
|
||||
for (i=(int)strlen(key_o) ; i<(int)strlen(key_i) ; i++) {
|
||||
line[i]=' ';
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name generate_default_convtab
|
||||
@memo Create a default conversion table.
|
||||
@param ins Table name.
|
||||
@return void
|
||||
@doc
|
||||
|
||||
Creates a translation table for the requested instrument. If no
|
||||
instrument is specified (ins==NULL) a default table is generated.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static void generate_default_convtab(void)
|
||||
{
|
||||
FILE * convtab ;
|
||||
|
||||
if ((convtab = fopen("table.conv", "w")) == NULL) {
|
||||
fprintf(stderr, "*** error: cannot create table.conv: aborting\n") ;
|
||||
return ;
|
||||
}
|
||||
fprintf(convtab, CONVTAB_DEFAULT);
|
||||
fclose(convtab) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name convert_deg_to_str
|
||||
@memo Convert decimal degrees to ASCII representation.
|
||||
@param d Double value, decimal degrees in [-90 ; +90].
|
||||
@return Pointer to statically allocated character string.
|
||||
@doc
|
||||
|
||||
Converts an angle value from degrees to ASCII representation
|
||||
following the IRAF convention. Do not free or modify the returned
|
||||
string.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static char * convert_deg_to_str( double deg )
|
||||
{
|
||||
int d, m;
|
||||
double s;
|
||||
int sign;
|
||||
static char buf[13];
|
||||
|
||||
sign = 1;
|
||||
if(deg < 0.) sign = -1;
|
||||
|
||||
deg *= sign;
|
||||
d = (int)deg;
|
||||
m = (int)( (deg - d) * 60);
|
||||
s = (deg - d) * 3600. - m * 60;
|
||||
|
||||
sprintf(buf, "'%c%02d:%02d:%06.3f'", (sign<0)? '-' : ' ', d, m, s);
|
||||
|
||||
return(buf);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,219 @@
|
|||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
||||
File name : replacekey.c
|
||||
Author : N. Devillard
|
||||
Created on : July 14th, 1998
|
||||
Description : Search & Replace operations in FITS headers
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: replacekey.c,v 1.1 2001/12/14 09:15:19 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2001/12/14 09:15:19 $
|
||||
$Revision: 1.1 $
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define NM_SIZ 512
|
||||
#define DEFAULT_PLACEHOLDER "COMMENT PLACEHOLDER"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Private functions and module variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static char prog_desc[] = "replace keyholder in a FITS header" ;
|
||||
|
||||
static void usage(char *) ;
|
||||
static int replace_placeholder(char *, char *, char*) ;
|
||||
static int get_FITS_header_size(char *) ;
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
main()
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char name_in[NM_SIZ] ;
|
||||
char placeholder[NM_SIZ] ;
|
||||
char card[NM_SIZ] ;
|
||||
|
||||
if (argc<3) usage(argv[0]) ;
|
||||
strncpy(name_in, argv[1], NM_SIZ) ;
|
||||
strncpy(card, argv[2], NM_SIZ) ;
|
||||
if (argc==4) {
|
||||
strncpy(placeholder, argv[3], NM_SIZ) ;
|
||||
} else {
|
||||
strncpy(placeholder, DEFAULT_PLACEHOLDER, NM_SIZ);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity tests
|
||||
*/
|
||||
if (strlen(card)>80) {
|
||||
fprintf(stderr, "requested card is too long: %d chars\n",strlen(card));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (replace_placeholder(name_in, card, placeholder) != 0) {
|
||||
fprintf(stderr, "error during placeholder replacement: aborting\n") ;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function only gives the usage for the program
|
||||
*/
|
||||
|
||||
static void usage(char *pname)
|
||||
{
|
||||
printf("%s : %s\n", pname, prog_desc) ;
|
||||
printf("use : %s <in> <card> [placeholder]\n", pname) ;
|
||||
printf("\n\n") ;
|
||||
exit(0) ;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function : replace_placeholder()
|
||||
In : name of the FITS file to modify, card to insert,
|
||||
name of the placeholder
|
||||
Out : int 0 if Ok, anything else otherwise
|
||||
Job : replaces a placeholder by a given FITS card
|
||||
Notice : modifies the input FITS file
|
||||
Does not check the validity of the given FITS card
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static int replace_placeholder(
|
||||
char * name_in,
|
||||
char * card,
|
||||
char * placeholder)
|
||||
{
|
||||
int fd ;
|
||||
char * buf ;
|
||||
char * where ;
|
||||
int hs ;
|
||||
|
||||
/*
|
||||
* mmap the FITS header of the input file
|
||||
*/
|
||||
|
||||
hs = get_FITS_header_size(name_in) ;
|
||||
if (hs < 1) {
|
||||
fprintf(stderr, "error getting FITS header size for %s\n", name_in);
|
||||
return -1 ;
|
||||
}
|
||||
fd = open(name_in, O_RDWR) ;
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "cannot open %s: aborting\n", name_in) ;
|
||||
return -1 ;
|
||||
}
|
||||
buf = (char*)mmap(0,
|
||||
hs,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
fd,
|
||||
0) ;
|
||||
if (buf == (char*)-1) {
|
||||
perror("mmap") ;
|
||||
fprintf(stderr, "cannot mmap file: %s\n", name_in) ;
|
||||
close(fd) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply search and replace for the input keyword lists
|
||||
*/
|
||||
|
||||
where = buf ;
|
||||
do {
|
||||
where = strstr(where, placeholder);
|
||||
if (where == NULL) {
|
||||
fprintf(stderr, "not found in input: [%s]\n", placeholder) ;
|
||||
close(fd);
|
||||
munmap(buf,hs);
|
||||
return -1 ;
|
||||
}
|
||||
} while ((where-buf)%80) ;
|
||||
|
||||
/* Replace current placeholder by blanks */
|
||||
memset(where, ' ', 80);
|
||||
/* Copy card into placeholder */
|
||||
memcpy(where, card, strlen(card));
|
||||
|
||||
close(fd) ;
|
||||
munmap(buf, hs) ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function : get_FITS_header_size()
|
||||
In : FITS file name
|
||||
Out : unsigned long
|
||||
Job : compute the size (in bytes) of a FITS header
|
||||
Notice : should always be a multiple of 2880. This implementation
|
||||
assumes only that 80 characters are found per line.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define FITS_BLSZ 2880
|
||||
static int get_FITS_header_size(char * name)
|
||||
{
|
||||
FILE * in ;
|
||||
char line[81] ;
|
||||
int found = 0 ;
|
||||
int count ;
|
||||
int hs ;
|
||||
|
||||
if ((in = fopen(name, "r")) == NULL) {
|
||||
fprintf(stderr, "cannot open %s: aborting\n", name) ;
|
||||
return 0 ;
|
||||
}
|
||||
count = 0 ;
|
||||
while (!found) {
|
||||
if (fread(line, 1, 80, in)!=80) {
|
||||
break ;
|
||||
}
|
||||
count ++ ;
|
||||
if (!strncmp(line, "END ", 4)) {
|
||||
found = 1 ;
|
||||
}
|
||||
}
|
||||
fclose(in);
|
||||
|
||||
if (!found) return 0 ;
|
||||
/*
|
||||
* The size is the number of found cards times 80,
|
||||
* rounded to the closest higher multiple of 2880.
|
||||
*/
|
||||
hs = count * 80 ;
|
||||
if ((hs % FITS_BLSZ) != 0) {
|
||||
hs = (1+(hs/FITS_BLSZ)) * FITS_BLSZ ;
|
||||
}
|
||||
return hs ;
|
||||
}
|
||||
#undef FITS_BLSZ
|
||||
|
||||
/*------------------------------ end of file ------------------------------*/
|
||||
|
|
@ -0,0 +1,365 @@
|
|||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
File name : stripfits.c
|
||||
Author : N. Devillard
|
||||
Created on : January 1999
|
||||
Description : Strip off FITS header to dump pixels only
|
||||
Notice : stand-alone
|
||||
|
||||
Compile with:
|
||||
gcc -o stripfits stripfits.c -O
|
||||
|
||||
This program dumps all the pixels from a FITS header into another file.
|
||||
It has been written in less than 10 minutes (reusing most of the code
|
||||
from iofits.c) to help the guys working on the ISAAC detector that day.
|
||||
Since it is a good example of how to write a stand-alone FITS command, I
|
||||
leave it here in the distribution.
|
||||
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: stripfits.c,v 1.1 2001/12/14 09:15:19 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2001/12/14 09:15:19 $
|
||||
$Revision: 1.1 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define NM_SIZ 512
|
||||
#define FITS_BLSZ 2880
|
||||
#define ONE_MEGABYTE (1024 * 1024)
|
||||
|
||||
#ifndef SEEK_SET
|
||||
#define SEEK_SET 0
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* All functions are private
|
||||
*/
|
||||
|
||||
static int dump_pix(char*, char*);
|
||||
static int get_FITS_header_size(char *) ;
|
||||
static int filesize(char*) ;
|
||||
static int get_bitpix(char*) ;
|
||||
static int get_npix(char*) ;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
main()
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc<3) {
|
||||
printf("\n\n") ;
|
||||
printf("use: %s <in> <out>\n", argv[0]) ;
|
||||
printf("\n") ;
|
||||
printf("\t<in> is a valid FITS file in the current directory\n") ;
|
||||
printf("\t<out> is the name of the output file\n") ;
|
||||
printf("\n\n") ;
|
||||
return 0 ;
|
||||
}
|
||||
if (!strcmp(argv[1], argv[2])) {
|
||||
fprintf(stderr, "cannot convert a file to itself\n") ;
|
||||
fprintf(stderr, "specify another name for the output\n") ;
|
||||
return -1 ;
|
||||
}
|
||||
return dump_pix(argv[1], argv[2]);
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function : dump_pix()
|
||||
In : name in, name out
|
||||
Out : int 0 if Ok, anything else otherwise
|
||||
Job : dump pixels from a FITS file to a binary file
|
||||
Notice : heavy use of mmap() to speed up the process
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
dump_pix(
|
||||
char * name_in,
|
||||
char * name_out
|
||||
)
|
||||
{
|
||||
int fd_in,
|
||||
fd_out ;
|
||||
char * buf_in ;
|
||||
char * buf_out ;
|
||||
int fsize_in,
|
||||
fsize_out,
|
||||
header_size ;
|
||||
int npix ;
|
||||
|
||||
/*
|
||||
* Open input file and get information we need:
|
||||
* - pixel depth
|
||||
* - number of pixels
|
||||
*/
|
||||
|
||||
fsize_in = filesize(name_in) ;
|
||||
header_size = get_FITS_header_size(name_in) ;
|
||||
if ((fd_in = open(name_in, O_RDONLY)) == -1) {
|
||||
fprintf(stderr, "cannot open file %s: aborting\n", name_in) ;
|
||||
return -1 ;
|
||||
}
|
||||
buf_in = (char*)mmap(0, fsize_in, PROT_READ, MAP_SHARED, fd_in, 0) ;
|
||||
if (buf_in == (char*)-1) {
|
||||
perror("mmap") ;
|
||||
fprintf(stderr, "cannot mmap file: %s\n", name_in) ;
|
||||
close(fd_in) ;
|
||||
return -1 ;
|
||||
}
|
||||
if (get_bitpix(buf_in) != -32) {
|
||||
fprintf(stderr, "only 32-bit IEEE floating point format supported\n");
|
||||
close(fd_in) ; munmap(buf_in, fsize_in) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the size of the output file
|
||||
* same header size, + pixel area + blank padding
|
||||
*/
|
||||
npix = get_npix(buf_in) ;
|
||||
if (npix < 1) {
|
||||
fprintf(stderr, "cannot compute number of pixels\n");
|
||||
close(fd_in) ;
|
||||
munmap(buf_in, fsize_in) ;
|
||||
return -1 ;
|
||||
}
|
||||
fsize_out = npix * 4 ;
|
||||
/*
|
||||
* Now create the output file and fill it with zeros, then mmap it.
|
||||
* The permissions are rw-rw-r-- by default.
|
||||
*/
|
||||
if ((fd_out=creat(name_out,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH))==-1){
|
||||
perror("creat") ;
|
||||
fprintf(stderr, "cannot create file %s: aborting\n", name_out) ;
|
||||
close(fd_in) ; munmap(buf_in, fsize_in) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
buf_out = malloc(fsize_out) ;
|
||||
if (buf_out == NULL) {
|
||||
fprintf(stderr, "not enough memory\n");
|
||||
fprintf(stderr, "failed to allocate %d bytes\n", fsize_out);
|
||||
close(fd_in) ; munmap(buf_in, fsize_in) ;
|
||||
return -1;
|
||||
}
|
||||
write(fd_out, buf_out, fsize_out);
|
||||
close(fd_out);
|
||||
free(buf_out);
|
||||
|
||||
fd_out = open(name_out, O_RDWR);
|
||||
if (fd_out==-1) {
|
||||
fprintf(stderr, "error opening file %s\n", name_out);
|
||||
close(fd_in) ; munmap(buf_in, fsize_in) ;
|
||||
return -1;
|
||||
}
|
||||
buf_out = (char*)mmap(0,
|
||||
fsize_out,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
fd_out,
|
||||
0) ;
|
||||
if (buf_out == (char*)-1) {
|
||||
perror("mmap") ;
|
||||
fprintf(stderr, "cannot mmap file: %s\n", name_out) ;
|
||||
munmap(buf_in, fsize_in) ; close(fd_in) ; close(fd_out) ;
|
||||
return -1 ;
|
||||
}
|
||||
/*
|
||||
* Copy FITS header from input to output, modify BITPIX
|
||||
*/
|
||||
memcpy(buf_out, buf_in+header_size, fsize_out) ;
|
||||
/*
|
||||
* Close, unmap, goodbye
|
||||
*/
|
||||
close(fd_in) ;
|
||||
close(fd_out) ;
|
||||
munmap(buf_in, fsize_in) ;
|
||||
munmap(buf_out, fsize_out) ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function : get_FITS_header_size()
|
||||
In : FITS file name
|
||||
Out : unsigned long
|
||||
Job : compute the size (in bytes) of a FITS header
|
||||
Notice : should always be a multiple of 2880. This implementation
|
||||
assumes only that 80 characters are found per line.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static int get_FITS_header_size(char * name)
|
||||
{
|
||||
FILE * in ;
|
||||
char line[81] ;
|
||||
int found = 0 ;
|
||||
int count ;
|
||||
int hs ;
|
||||
|
||||
if ((in = fopen(name, "r")) == NULL) {
|
||||
fprintf(stderr, "cannot open %s: aborting\n", name) ;
|
||||
return 0 ;
|
||||
}
|
||||
count = 0 ;
|
||||
while (!found) {
|
||||
if (fread(line, 1, 80, in)!=80) {
|
||||
break ;
|
||||
}
|
||||
count ++ ;
|
||||
if (!strncmp(line, "END ", 4)) {
|
||||
found = 1 ;
|
||||
}
|
||||
}
|
||||
fclose(in);
|
||||
|
||||
if (!found) return 0 ;
|
||||
/*
|
||||
* The size is the number of found cards times 80,
|
||||
* rounded to the closest higher multiple of 2880.
|
||||
*/
|
||||
hs = count * 80 ;
|
||||
if ((hs % FITS_BLSZ) != 0) {
|
||||
hs = (1+(hs/FITS_BLSZ)) * FITS_BLSZ ;
|
||||
}
|
||||
return hs ;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Function : filesize()
|
||||
* In : filename
|
||||
* Out : size of the file in bytes
|
||||
* Job : strongly non portable. Only on Unix systems!
|
||||
* Notice : Looks strange, but there is no portable way to answer
|
||||
* the question: how many bytes can I read from this file?
|
||||
*--------------------------------------------------------------------------*/
|
||||
|
||||
static int filesize(char *filename)
|
||||
{
|
||||
int size ;
|
||||
struct stat fileinfo ;
|
||||
|
||||
/* POSIX compliant */
|
||||
if (stat(filename, &fileinfo) != 0) {
|
||||
size = (int)0 ;
|
||||
} else {
|
||||
size = (int)fileinfo.st_size ;
|
||||
}
|
||||
return size ;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function : get_bitpix()
|
||||
In : allocated char buffer containing the whole FITS header
|
||||
Out : int 8 16 32 -32 or -64
|
||||
Job : gets the value of BITPIX from a FITS header
|
||||
Notice : returns 0 if cannot find it
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static
|
||||
int get_bitpix(char * buf)
|
||||
{
|
||||
int bitpix ;
|
||||
char * where ;
|
||||
|
||||
where = strstr(buf, "BITPIX") ;
|
||||
if (where == NULL) {
|
||||
fprintf(stderr, "cannot find BITPIX in header: aborting\n") ;
|
||||
return 0 ;
|
||||
}
|
||||
sscanf(where, "%*[^=] = %d", &bitpix) ;
|
||||
/*
|
||||
* Check the returned value makes sense
|
||||
*/
|
||||
if ((bitpix != 8) &&
|
||||
(bitpix != 16) &&
|
||||
(bitpix != 32) &&
|
||||
(bitpix != -32) &&
|
||||
(bitpix != -64)) {
|
||||
bitpix = 0 ;
|
||||
}
|
||||
return bitpix ;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function : get_npix()
|
||||
In : allocated char buffer containing the complete FITS header
|
||||
Out : unsigned long: # of pixels in the file
|
||||
Job : retrieves how many pixels in a FITS file from the header
|
||||
Notice : does not support extensions!
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static
|
||||
int get_npix(char * buf)
|
||||
{
|
||||
int naxes ;
|
||||
int npix ;
|
||||
int naxis ;
|
||||
char * where ;
|
||||
char lookfor[80] ;
|
||||
int i ;
|
||||
|
||||
where = strstr(buf, "NAXIS") ;
|
||||
if (where == NULL) {
|
||||
fprintf(stderr, "cannot find NAXIS in header: aborting\n") ;
|
||||
return 0 ;
|
||||
}
|
||||
sscanf(where, "%*[^=] = %d", &naxes) ;
|
||||
if ((naxes<1) || (naxes>999)) {
|
||||
fprintf(stderr, "illegal value for %s: %d\n", lookfor, naxes) ;
|
||||
return 0 ;
|
||||
}
|
||||
npix = 1 ;
|
||||
for (i=1 ; i<=naxes ; i++) {
|
||||
sprintf(lookfor, "NAXIS%d", i) ;
|
||||
where = strstr(buf, lookfor) ;
|
||||
if (where == NULL) {
|
||||
fprintf(stderr, "cannot find %s in header: aborting\n",
|
||||
lookfor) ;
|
||||
return 0 ;
|
||||
}
|
||||
sscanf(where, "%*[^=] = %d", &naxis) ;
|
||||
if (naxis<1) {
|
||||
fprintf(stderr, "error: found %s=%d\n", lookfor, naxis);
|
||||
return 0 ;
|
||||
}
|
||||
npix *= (int)naxis ;
|
||||
}
|
||||
return npix ;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env python
|
||||
"""Setup script for the Qfits module distribution."""
|
||||
from distutils.core import setup, Extension
|
||||
import glob
|
||||
import os.path
|
||||
|
||||
setup (# Distribution meta-data
|
||||
name = "Qfits",
|
||||
version = "4.0",
|
||||
description = "FITS header parsing module",
|
||||
author = "Nicolas Devillard",
|
||||
author_email = "nDevil at eso dot org",
|
||||
url = "http://archive.eso.org/saft/qfits",
|
||||
|
||||
# Description of the modules and packages in the distribution
|
||||
# packages = [''],
|
||||
package_dir = {'': 'python'},
|
||||
py_modules = ['Qfits'],
|
||||
ext_modules =
|
||||
[Extension('qfits', glob.glob(os.path.join('src', '*.c')),
|
||||
include_dirs=["./include"],
|
||||
library_dirs=[''],
|
||||
libraries=[''],),
|
||||
]
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
config.h
|
|
@ -0,0 +1,149 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file byteswap.c
|
||||
@author N. Devillard
|
||||
@date Sep 1999
|
||||
@version $Revision: 1.6 $
|
||||
@brief Low-level byte-swapping routines
|
||||
|
||||
This module offers access to byte-swapping routines.
|
||||
Generic routines are offered that should work everywhere.
|
||||
Assembler is also included for x86 architectures, and dedicated
|
||||
assembler calls for processors > 386.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: byteswap.c,v 1.6 2002/01/22 14:49:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/22 14:49:08 $
|
||||
$Revision: 1.6 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** Potential tracing feature for gcc > 2.95 */
|
||||
#if (__GNUC__>2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ > 95))
|
||||
#define __NOTRACE__ __attribute__((__no_instrument_function__))
|
||||
#else
|
||||
#define __NOTRACE__
|
||||
#endif
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Swap a 16-bit number
|
||||
@param w A 16-bit (short) number to byte-swap.
|
||||
@return The swapped version of w, w is untouched.
|
||||
|
||||
This function swaps a 16-bit number, returned the swapped value without
|
||||
modifying the passed argument. Assembler included for x86 architectures.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
unsigned short __NOTRACE__ swap_bytes_16(unsigned short w)
|
||||
{
|
||||
#ifdef CPU_X86
|
||||
__asm("xchgb %b0,%h0" :
|
||||
"=q" (w) :
|
||||
"0" (w));
|
||||
return w ;
|
||||
#else
|
||||
return (((w) & 0x00ff) << 8 | ((w) & 0xff00) >> 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Swap a 32-bit number
|
||||
@param dw A 32-bit (long) number to byte-swap.
|
||||
@return The swapped version of dw, dw is untouched.
|
||||
|
||||
This function swaps a 32-bit number, returned the swapped value without
|
||||
modifying the passed argument. Assembler included for x86 architectures
|
||||
and optimized for processors above 386.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
unsigned int __NOTRACE__ swap_bytes_32(unsigned int dw)
|
||||
{
|
||||
#ifdef CPU_X86
|
||||
#if CPU_X86 > 386
|
||||
__asm("bswap %0":
|
||||
"=r" (dw) :
|
||||
#else
|
||||
__asm("xchgb %b0,%h0\n"
|
||||
" rorl $16,%0\n"
|
||||
" xchgb %b0,%h0":
|
||||
"=q" (dw) :
|
||||
#endif
|
||||
"0" (dw));
|
||||
return dw ;
|
||||
#else
|
||||
return ((((dw) & 0xff000000) >> 24) | (((dw) & 0x00ff0000) >> 8) |
|
||||
(((dw) & 0x0000ff00) << 8) | (((dw) & 0x000000ff) << 24));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@fn swap_bytes
|
||||
@brief Swaps bytes in a variable of given size
|
||||
@param p pointer to void (generic pointer)
|
||||
@param s size of the element to swap, pointed to by p
|
||||
@return void
|
||||
|
||||
This byte-swapper is portable and works for any even variable size.
|
||||
It is not truly the most efficient ever, but does its job fine
|
||||
everywhere this file compiles.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void __NOTRACE__ swap_bytes(void * p, int s)
|
||||
{
|
||||
unsigned char tmp, *a, *b ;
|
||||
|
||||
a = (unsigned char*)p ;
|
||||
b = a + s ;
|
||||
|
||||
while (a<b) {
|
||||
tmp = *a ;
|
||||
*a++ = *--b ;
|
||||
*b = tmp ;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Find out if the local machine is big or little endian
|
||||
@return int 1 if local machine needs byteswapping (INTEL), 0 else.
|
||||
|
||||
This function determines at run-time the endian-ness of the local
|
||||
machine. An INTEL-like processor needs byte-swapping, a
|
||||
MOTOROLA-like one does not.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int need_byteswapping(void)
|
||||
{
|
||||
short ps = 0xFF ;
|
||||
return ((*((char*)(&ps))) ? 1 : 0 ) ;
|
||||
}
|
||||
|
||||
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,95 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file byteswap.h
|
||||
@author N. Devillard
|
||||
@date Sep 1999
|
||||
@version $Revision: 1.4 $
|
||||
@brief Low-level byte-swapping routines
|
||||
|
||||
This module offers access to byte-swapping routines.
|
||||
Generic routines are offered that should work everywhere.
|
||||
Assembler is also included for x86 architectures, and dedicated
|
||||
assembler calls for processors > 386.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: byteswap.h,v 1.4 2002/01/22 14:38:37 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/22 14:38:37 $
|
||||
$Revision: 1.4 $
|
||||
*/
|
||||
|
||||
#ifndef _BYTESWAP_H_
|
||||
#define _BYTESWAP_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function ANSI C prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Swap a 16-bit number
|
||||
@param w A 16-bit (short) number to byte-swap.
|
||||
@return The swapped version of w, w is untouched.
|
||||
|
||||
This function swaps a 16-bit number, returned the swapped value without
|
||||
modifying the passed argument. Assembler included for x86 architectures.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
unsigned short swap_bytes_16(unsigned short w);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Swap a 32-bit number
|
||||
@param dw A 32-bit (long) number to byte-swap.
|
||||
@return The swapped version of dw, dw is untouched.
|
||||
|
||||
This function swaps a 32-bit number, returned the swapped value without
|
||||
modifying the passed argument. Assembler included for x86 architectures
|
||||
and optimized for processors above 386.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
unsigned int swap_bytes_32(unsigned int dw);
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Swaps bytes in a variable of given size
|
||||
@param p pointer to void (generic pointer)
|
||||
@param s size of the element to swap, pointed to by p
|
||||
@return void
|
||||
|
||||
This byte-swapper is portable and works for any even variable size.
|
||||
It is not truly the most efficient ever, but does its job fine
|
||||
everywhere this file compiles.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void swap_bytes(void * p, int s);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Find out if the local machine is big or little endian
|
||||
@return int 1 if local machine needs byteswapping (INTEL), 0 else.
|
||||
|
||||
This function determines at run-time the endian-ness of the local
|
||||
machine. An INTEL-like processor needs byte-swapping, a
|
||||
MOTOROLA-like one does not.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int need_byteswapping(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,731 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file cache.c
|
||||
@author N. Devillard
|
||||
@date Mar 2001
|
||||
@version $Revision: 1.2 $
|
||||
@brief FITS caching capabilities
|
||||
|
||||
This modules implements a cache for FITS access routines.
|
||||
The first time a FITS file is seen by the library, all corresponding
|
||||
pointers are cached here. This speeds up multiple accesses to large
|
||||
files by magnitudes.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: cache.c,v 1.2 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.2 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "static_sz.h"
|
||||
#include "cache.h"
|
||||
#include "fits_p.h"
|
||||
#include "fits_std.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** Define this symbol to get debug symbols -- not recommended! */
|
||||
#define QFITS_CACHE_DEBUG 0
|
||||
#if QFITS_CACHE_DEBUG
|
||||
#define qdebug( code ) { code }
|
||||
#else
|
||||
#define qdebug( code )
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Minimum cache size: this avoids repeated mallocs to increase
|
||||
* the cache size for every new file. The first table already contains
|
||||
* space for MINSZ entries, and its size is doubled every time it is
|
||||
* overflowed.
|
||||
*/
|
||||
#define QFITS_CACHE_MINSZ 128
|
||||
|
||||
/**
|
||||
* Maximum cache size: the cache will be purged every time the number of
|
||||
* input FITS files reaches above this limit. This avoids having the cache
|
||||
* grow infinitely.
|
||||
*/
|
||||
|
||||
#define QFITS_CACHE_MAXSZ 4096
|
||||
|
||||
|
||||
/**
|
||||
* This static definition declares the maximum possible number of
|
||||
* extensions in a FITS file. It only has effects in the qfits_cache_add
|
||||
* function where a table is statically allocated for efficiency reasons.
|
||||
* If the number of extensions grows over this limit, change the value of
|
||||
* this constant. If the number of extensions is a priori unknown but can
|
||||
* grow much larger than a predictable value, the best solution is to
|
||||
* implement a dynamic memory allocation in qfits_cache_add.
|
||||
*/
|
||||
|
||||
#define QFITS_MAX_EXTS 128
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
New types
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Cache cell (private)
|
||||
|
||||
This structure stores all informations about a given FITS file.
|
||||
It is strictly internal to this module.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
typedef struct _qfits_cache_cell_ {
|
||||
char * name ; /* File name */
|
||||
unsigned hash ;
|
||||
time_t mtime; /* Last modification date */
|
||||
time_t ctime; /* Last modification date */
|
||||
|
||||
int exts ; /* # of extensions in file */
|
||||
|
||||
int * ohdr ; /* Offsets to headers */
|
||||
int * shdr ; /* Header sizes */
|
||||
int * data ; /* Offsets to data */
|
||||
int * dsiz ; /* Data sizes */
|
||||
} qfits_cache_cell ;
|
||||
|
||||
|
||||
static qfits_cache_cell * qfits_cache = NULL ;
|
||||
static int qfits_cache_last = -1 ;
|
||||
static int qfits_cache_size = 0 ;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Globals (private to this module)
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static void * mem_double(void * ptr, int size);
|
||||
static void qfits_cache_activate(void);
|
||||
static unsigned qfits_cache_hash(char * key);
|
||||
static int qfits_is_cached(char * filename);
|
||||
static int qfits_cache_add(char * name);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Doubles the allocated size associated to a pointer */
|
||||
/* 'size' is the current allocated size. */
|
||||
static void * mem_double(void * ptr, int size)
|
||||
{
|
||||
void * newptr ;
|
||||
|
||||
newptr = calloc(2*size, 1);
|
||||
memcpy(newptr, ptr, size);
|
||||
free(ptr);
|
||||
return newptr ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Activate cache: initialize cache buffer with minimum size
|
||||
*/
|
||||
|
||||
static void qfits_cache_activate(void)
|
||||
{
|
||||
qdebug(
|
||||
printf("qfits: activating cache...\n");
|
||||
);
|
||||
/* Allocate new array for cache cells */
|
||||
qfits_cache = malloc(QFITS_CACHE_MINSZ * sizeof(qfits_cache_cell));
|
||||
qfits_cache_size = QFITS_CACHE_MINSZ ;
|
||||
/* Register purge function with atexit */
|
||||
atexit(qfits_cache_purge);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Purge the qfits cache.
|
||||
@return void
|
||||
|
||||
This function is useful for programs running for a long period,
|
||||
to clean up the cache. Ideally in a daemon, it should be called
|
||||
by a timer at regular intervals. Notice that since the cache is
|
||||
fairly small, you should not need to care too much about this.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void qfits_cache_purge(void)
|
||||
{
|
||||
int i ;
|
||||
|
||||
if (qfits_cache==NULL)
|
||||
return ;
|
||||
qdebug(
|
||||
printf("qfits: purging cache...\n");
|
||||
);
|
||||
|
||||
for (i=0 ; i<qfits_cache_last ; i++) {
|
||||
if (qfits_cache[i].name!=NULL)
|
||||
free(qfits_cache[i].name);
|
||||
if (qfits_cache[i].ohdr!=NULL)
|
||||
free(qfits_cache[i].ohdr);
|
||||
if (qfits_cache[i].data!=NULL)
|
||||
free(qfits_cache[i].data);
|
||||
if (qfits_cache[i].shdr!=NULL)
|
||||
free(qfits_cache[i].shdr);
|
||||
if (qfits_cache[i].dsiz!=NULL)
|
||||
free(qfits_cache[i].dsiz);
|
||||
}
|
||||
free(qfits_cache);
|
||||
qfits_cache = NULL ;
|
||||
qfits_cache_size = 0 ;
|
||||
qfits_cache_last = -1 ;
|
||||
return ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple hash function to speed up name lookups
|
||||
*/
|
||||
static unsigned qfits_cache_hash(char * key)
|
||||
{
|
||||
int len ;
|
||||
unsigned hash ;
|
||||
int i ;
|
||||
|
||||
len = strlen(key);
|
||||
for (hash=0, i=0 ; i<len ; i++) {
|
||||
hash += (unsigned)key[i] ;
|
||||
hash += (hash<<10);
|
||||
hash ^= (hash>>6) ;
|
||||
}
|
||||
hash += (hash <<3);
|
||||
hash ^= (hash >>11);
|
||||
hash += (hash <<15);
|
||||
return hash ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Find out if a file is in the cache already
|
||||
*/
|
||||
static int qfits_is_cached(char * filename)
|
||||
{
|
||||
int i ;
|
||||
unsigned h ;
|
||||
struct stat sta ;
|
||||
|
||||
if (stat(filename, &sta)!=0) {
|
||||
return -1 ;
|
||||
}
|
||||
h = qfits_cache_hash(filename);
|
||||
for (i=0 ; i<=qfits_cache_last ; i++) {
|
||||
if (qfits_cache[i].hash == h) {
|
||||
if (!strcmp(qfits_cache[i].name, filename)) {
|
||||
if ((qfits_cache[i].mtime == sta.st_mtime) &&
|
||||
(qfits_cache[i].ctime == sta.st_ctime)) {
|
||||
return i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Query a FITS file offset from the cache.
|
||||
@param filename Name of the file to examine.
|
||||
@param what What should be queried (see below).
|
||||
@return an integer offset, or -1 if an error occurred.
|
||||
|
||||
This function queries the cache for FITS offset information. If the
|
||||
requested file name has never been seen before, it is completely parsed
|
||||
to extract all offset informations, which are then stored in the cache.
|
||||
The next query will get the informations from the cache, avoiding
|
||||
a complete re-parsing of the file. This is especially useful for large
|
||||
FITS files with lots of extensions, because querying the extensions
|
||||
is an expensive operation.
|
||||
|
||||
This operation has side-effects: the cache is an automatically
|
||||
allocated structure in memory, that can only grow. Every request
|
||||
on a new FITS file will make it grow. The structure is pretty
|
||||
light-weight in memory, but nonetheless this is an issue for daemon-type
|
||||
programs which must run over long periods. The solution is to clean
|
||||
the cache using qfits_cache_purge() at regular intervals. This is left
|
||||
to the user of this library.
|
||||
|
||||
To request information about a FITS file, you must pass an integer
|
||||
built from the following symbols:
|
||||
|
||||
- @c QFITS_QUERY_N_EXT
|
||||
- @c QFITS_QUERY_HDR_START
|
||||
- @c QFITS_QUERY_DAT_START
|
||||
- @c QFITS_QUERY_HDR_SIZE
|
||||
- @c QFITS_QUERY_DAT_SIZE
|
||||
|
||||
Querying the number of extensions present in a file is done
|
||||
simply with:
|
||||
|
||||
@code
|
||||
next = qfits_query(filename, QFITS_QUERY_N_EXT);
|
||||
@endcode
|
||||
|
||||
Querying the offset to the i-th extension header is done with:
|
||||
|
||||
@code
|
||||
off = qfits_query(filename, QFITS_QUERY_HDR_START | i);
|
||||
@endcode
|
||||
|
||||
i.e. you must OR (|) the extension number with the
|
||||
@c QFITS_QUERY_HDR_START symbol. Requesting offsets to extension data is
|
||||
done in the same way:
|
||||
|
||||
@code
|
||||
off = qfits_query(filename, QFITS_QUERY_DAT_START | i);
|
||||
@endcode
|
||||
|
||||
Notice that extension 0 is the main header and main data part
|
||||
of the FITS file.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_query(char * filename, int what)
|
||||
{
|
||||
int rank ;
|
||||
int which ;
|
||||
int answer ;
|
||||
|
||||
if (qfits_cache==NULL)
|
||||
qfits_cache_activate();
|
||||
|
||||
if (qfits_cache_last > QFITS_CACHE_MAXSZ) {
|
||||
/* Call a purge of the cache */
|
||||
qfits_cache_purge();
|
||||
qfits_cache_activate();
|
||||
}
|
||||
|
||||
qdebug(
|
||||
printf("qfits: cache req %s\n", filename);
|
||||
);
|
||||
if ((rank=qfits_is_cached(filename))==-1) {
|
||||
rank = qfits_cache_add(filename);
|
||||
}
|
||||
if (rank==-1) {
|
||||
qdebug(
|
||||
printf("qfits: error adding %s to cache\n", filename);
|
||||
);
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* See what was requested */
|
||||
answer=-1 ;
|
||||
if (what & QFITS_QUERY_N_EXT) {
|
||||
qdebug(
|
||||
printf("qfits: query n_exts\n");
|
||||
);
|
||||
answer = qfits_cache[rank].exts ;
|
||||
} else if (what & QFITS_QUERY_HDR_START) {
|
||||
which = what & (~QFITS_QUERY_HDR_START);
|
||||
if (which>=0 && which<=qfits_cache[rank].exts) {
|
||||
answer = qfits_cache[rank].ohdr[which] * FITS_BLOCK_SIZE ;
|
||||
}
|
||||
qdebug(
|
||||
printf("qfits: query offset to header %d\n", which);
|
||||
);
|
||||
} else if (what & QFITS_QUERY_DAT_START) {
|
||||
which = what & (~QFITS_QUERY_DAT_START);
|
||||
if (which>=0 && which<=qfits_cache[rank].exts) {
|
||||
answer = qfits_cache[rank].data[which] * FITS_BLOCK_SIZE ;
|
||||
}
|
||||
qdebug(
|
||||
printf("qfits: query offset to data %d\n", which);
|
||||
);
|
||||
} else if (what & QFITS_QUERY_HDR_SIZE) {
|
||||
which = what & (~QFITS_QUERY_HDR_SIZE);
|
||||
if (which>=0 && which<=qfits_cache[rank].exts) {
|
||||
answer = qfits_cache[rank].shdr[which] * FITS_BLOCK_SIZE ;
|
||||
}
|
||||
qdebug(
|
||||
printf("qfits: query sizeof header %d\n", which);
|
||||
);
|
||||
} else if (what & QFITS_QUERY_DAT_SIZE) {
|
||||
which = what & (~QFITS_QUERY_DAT_SIZE);
|
||||
if (which>=0 && which<=qfits_cache[rank].exts) {
|
||||
answer = qfits_cache[rank].dsiz[which] * FITS_BLOCK_SIZE ;
|
||||
}
|
||||
qdebug(
|
||||
printf("qfits: query sizeof data %d\n", which);
|
||||
);
|
||||
}
|
||||
return answer ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Add pointer information about a file into the qfits cache.
|
||||
@param filename Name of the file to examine.
|
||||
@return index to the file information in the cache, or -1 if failure.
|
||||
|
||||
This is the meat of this whole caching business.
|
||||
|
||||
This function picks a file name, and examines the corresponding FITS file
|
||||
to deduce all relevant pointers in the file (byte offsets). These byte
|
||||
offsets are later used to speed up header lookups. Example: requesting
|
||||
some keyword information in the header of the n-th extension will first
|
||||
fseek the file to the header start, then search from this position
|
||||
onwards. This means that the input FITS file is only parsed for extension
|
||||
positions once.
|
||||
|
||||
What this function does is:
|
||||
|
||||
- Open the file, read the first FITS block (@c FITS_BLOCK_SIZE bytes)
|
||||
- Check the file is FITS (must have SIMPLE = at top)
|
||||
- Register start of first header at offset 0.
|
||||
- Look for END keyword, register start of first data section
|
||||
if NAXIS>0.
|
||||
- If the EXTEND=T line was found, continue looking for extensions.
|
||||
- For each consecutive extension, register extension header start
|
||||
and extension data start.
|
||||
|
||||
The initial implementation of this module made use of an mmap() call
|
||||
to make the whole file available for search, but this is highly
|
||||
unefficient on HPUX, probably because of a weak mmap() implementation
|
||||
combined with very slow filesystems. The current implementation makes
|
||||
block reads, which should be much faster.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static int qfits_cache_add(char * filename)
|
||||
{
|
||||
FILE * in ;
|
||||
int off_hdr[QFITS_MAX_EXTS];
|
||||
int off_dat[QFITS_MAX_EXTS];
|
||||
int i ;
|
||||
char buf[FITS_BLOCK_SIZE] ;
|
||||
char * buf_c ;
|
||||
int n_blocks ;
|
||||
int found_it ;
|
||||
int xtend ;
|
||||
int naxis ;
|
||||
char * read_val ;
|
||||
int last ;
|
||||
int end_of_file ;
|
||||
int npix ;
|
||||
int skip_blocks ;
|
||||
struct stat sta ;
|
||||
|
||||
qfits_cache_cell * qc ;
|
||||
|
||||
/* Stat file to get its size */
|
||||
if (stat(filename, &sta)!=0) {
|
||||
qdebug(
|
||||
printf("qfits: cannot stat file %s\n", filename);
|
||||
);
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* Open input file */
|
||||
if ((in=fopen(filename, "r"))==NULL) {
|
||||
qdebug(
|
||||
printf("qfits: cannot open file %s\n", filename);
|
||||
);
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* Read first block in */
|
||||
if (fread(buf, 1, FITS_BLOCK_SIZE, in)!=FITS_BLOCK_SIZE) {
|
||||
qdebug(
|
||||
printf("qfits: error reading first block from %s\n", filename);
|
||||
);
|
||||
fclose(in);
|
||||
return -1 ;
|
||||
}
|
||||
/* Identify FITS magic number */
|
||||
if (buf[0]!='S' ||
|
||||
buf[1]!='I' ||
|
||||
buf[2]!='M' ||
|
||||
buf[3]!='P' ||
|
||||
buf[4]!='L' ||
|
||||
buf[5]!='E' ||
|
||||
buf[6]!=' ' ||
|
||||
buf[7]!=' ' ||
|
||||
buf[8]!='=') {
|
||||
qdebug(
|
||||
printf("qfits: file %s is not FITS\n", filename);
|
||||
);
|
||||
fclose(in);
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Browse through file to identify primary HDU size and see if there
|
||||
* might be some extensions. The size of the primary data zone will
|
||||
* also be estimated from the gathering of the NAXIS?? values and
|
||||
* BITPIX.
|
||||
*/
|
||||
|
||||
/* Rewind input file, END card might be in first block */
|
||||
rewind(in);
|
||||
|
||||
/* Initialize all counters */
|
||||
n_blocks = 0 ;
|
||||
found_it = 0 ;
|
||||
xtend = 0 ;
|
||||
naxis = 0 ;
|
||||
npix = 1 ;
|
||||
|
||||
/* Start looking for END card */
|
||||
while (found_it==0) {
|
||||
/* Read one FITS block */
|
||||
if (fread(buf, 1, FITS_BLOCK_SIZE, in)!=FITS_BLOCK_SIZE) {
|
||||
qdebug(
|
||||
printf("qfits: error reading file %s\n", filename);
|
||||
);
|
||||
fclose(in);
|
||||
return -1 ;
|
||||
}
|
||||
/* Browse through current block */
|
||||
buf_c = buf ;
|
||||
for (i=0 ; i<FITS_NCARDS ; i++) {
|
||||
|
||||
/* Look for BITPIX keyword */
|
||||
if (buf_c[0]=='B' &&
|
||||
buf_c[1]=='I' &&
|
||||
buf_c[2]=='T' &&
|
||||
buf_c[3]=='P' &&
|
||||
buf_c[4]=='I' &&
|
||||
buf_c[5]=='X' &&
|
||||
buf_c[6]==' ') {
|
||||
read_val = qfits_getvalue(buf_c);
|
||||
npix *= (int)atoi(read_val) / 8 ;
|
||||
if (npix<0) {
|
||||
npix=-npix ;
|
||||
}
|
||||
} else
|
||||
/* Look for NAXIS keyword */
|
||||
if (buf_c[0]=='N' &&
|
||||
buf_c[1]=='A' &&
|
||||
buf_c[2]=='X' &&
|
||||
buf_c[3]=='I' &&
|
||||
buf_c[4]=='S') {
|
||||
|
||||
if (buf_c[5]==' ') {
|
||||
/* NAXIS keyword */
|
||||
read_val = qfits_getvalue(buf_c);
|
||||
naxis = (int)atoi(read_val);
|
||||
} else {
|
||||
/* NAXIS?? keyword (axis size) */
|
||||
read_val = qfits_getvalue(buf_c);
|
||||
npix *= (int)atoi(read_val);
|
||||
}
|
||||
} else
|
||||
/* Look for EXTEND keyword */
|
||||
if (buf_c[0]=='E' &&
|
||||
buf_c[1]=='X' &&
|
||||
buf_c[2]=='T' &&
|
||||
buf_c[3]=='E' &&
|
||||
buf_c[4]=='N' &&
|
||||
buf_c[5]=='D' &&
|
||||
buf_c[6]==' ') {
|
||||
/* The EXTEND keyword is present: might be some extensions */
|
||||
read_val = qfits_getvalue(buf_c);
|
||||
if (read_val[0]=='T' || read_val[0]=='1') {
|
||||
xtend=1 ;
|
||||
}
|
||||
} else
|
||||
/* Look for END keyword */
|
||||
if (buf_c[0] == 'E' &&
|
||||
buf_c[1] == 'N' &&
|
||||
buf_c[2] == 'D' &&
|
||||
buf_c[3] == ' ') {
|
||||
found_it = 1 ;
|
||||
}
|
||||
buf_c += FITS_LINESZ ;
|
||||
}
|
||||
n_blocks ++ ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare qfits cache for addition of a new entry
|
||||
*/
|
||||
qfits_cache_last++ ;
|
||||
if (qfits_cache_last==qfits_cache_size) {
|
||||
/* New entry goes over allocated size: double the cache size */
|
||||
qdebug(
|
||||
printf("qfits: doubling cache size\n");
|
||||
);
|
||||
qfits_cache =
|
||||
mem_double(qfits_cache,
|
||||
2 * qfits_cache_size * sizeof(qfits_cache_cell));
|
||||
qfits_cache_size *= 2 ;
|
||||
}
|
||||
/* Alias to current pointer in cache for easier reading */
|
||||
qc = &(qfits_cache[qfits_cache_last]);
|
||||
|
||||
/* Initialize cache cell */
|
||||
qc->exts=0 ;
|
||||
qc->name = strdup(filename);
|
||||
qc->hash = qfits_cache_hash(filename);
|
||||
|
||||
/* Set first HDU offsets */
|
||||
off_hdr[0] = 0 ;
|
||||
off_dat[0] = n_blocks ;
|
||||
|
||||
/* Last is the pointer to the last added extension, plus one. */
|
||||
last = 1 ;
|
||||
|
||||
if (xtend) {
|
||||
/* Look for extensions */
|
||||
qdebug(
|
||||
printf("qfits: searching for extensions in %s\n", filename);
|
||||
);
|
||||
|
||||
/*
|
||||
* Skip the first data section if pixels were declared
|
||||
*/
|
||||
if (naxis>0) {
|
||||
/* Skip as many blocks as there are declared pixels */
|
||||
skip_blocks = npix/FITS_BLOCK_SIZE ;
|
||||
if ((npix % FITS_BLOCK_SIZE)!=0) {
|
||||
skip_blocks ++ ;
|
||||
}
|
||||
fseek(in, skip_blocks*FITS_BLOCK_SIZE, SEEK_CUR);
|
||||
/* Increase counter of current seen blocks. */
|
||||
n_blocks += skip_blocks ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register all extension offsets
|
||||
*/
|
||||
end_of_file = 0 ;
|
||||
while (end_of_file==0) {
|
||||
/* Look for extension start */
|
||||
found_it=0 ;
|
||||
while ((found_it==0) && (end_of_file==0)) {
|
||||
if (fread(buf, 1, FITS_BLOCK_SIZE, in)!=FITS_BLOCK_SIZE) {
|
||||
/* Reached end of file */
|
||||
end_of_file=1 ;
|
||||
break ;
|
||||
}
|
||||
/* Search for XTENSION at block top */
|
||||
if (buf[0]=='X' &&
|
||||
buf[1]=='T' &&
|
||||
buf[2]=='E' &&
|
||||
buf[3]=='N' &&
|
||||
buf[4]=='S' &&
|
||||
buf[5]=='I' &&
|
||||
buf[6]=='O' &&
|
||||
buf[7]=='N' &&
|
||||
buf[8]=='=') {
|
||||
/* Got an extension */
|
||||
found_it=1 ;
|
||||
off_hdr[last] = n_blocks ;
|
||||
}
|
||||
n_blocks ++ ;
|
||||
}
|
||||
if (end_of_file && found_it) {
|
||||
/* Reached end of file but was expecting an END */
|
||||
qdebug(
|
||||
printf("qfits: XTENSION without END in %s\n", filename);
|
||||
);
|
||||
break ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for extension END
|
||||
* Rewind one block backwards, END might be in same section as
|
||||
* XTENSION start.
|
||||
*/
|
||||
if (fseek(in, -FITS_BLOCK_SIZE, SEEK_CUR)!=0) {
|
||||
qdebug(
|
||||
printf("qfits: error fseeking file backwards\n");
|
||||
) ;
|
||||
fclose(in);
|
||||
return -1 ;
|
||||
}
|
||||
n_blocks -- ;
|
||||
found_it=0 ;
|
||||
while ((found_it==0) && (end_of_file==0)) {
|
||||
if (fread(buf, 1, FITS_BLOCK_SIZE, in)!=FITS_BLOCK_SIZE) {
|
||||
qdebug(
|
||||
printf("qfits: XTENSION without END in %s\n", filename);
|
||||
);
|
||||
end_of_file=1;
|
||||
break ;
|
||||
}
|
||||
|
||||
/* Browse current block for END */
|
||||
buf_c = buf ;
|
||||
for (i=0 ; i<FITS_NCARDS ; i++) {
|
||||
if (buf_c[0]=='E' &&
|
||||
buf_c[1]=='N' &&
|
||||
buf_c[2]=='D' &&
|
||||
buf_c[3]==' ') {
|
||||
/* Got the END card */
|
||||
found_it=1 ;
|
||||
/* Update registered extension list */
|
||||
off_dat[last] = n_blocks+1 ;
|
||||
last ++ ;
|
||||
qc->exts ++ ;
|
||||
break ;
|
||||
}
|
||||
buf_c+=FITS_LINESZ ;
|
||||
}
|
||||
n_blocks++ ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close file */
|
||||
fclose(in);
|
||||
|
||||
/* Allocate buffers in cache */
|
||||
qc->ohdr = malloc(last * sizeof(int));
|
||||
qc->data = malloc(last * sizeof(int));
|
||||
qc->shdr = malloc(last * sizeof(int));
|
||||
qc->dsiz = malloc(last * sizeof(int));
|
||||
/* Store retrieved pointers in the cache */
|
||||
for (i=0 ; i<last ; i++) {
|
||||
/* Offsets to start */
|
||||
qc->ohdr[i] = off_hdr[i];
|
||||
qc->data[i] = off_dat[i];
|
||||
|
||||
/* Sizes */
|
||||
qc->shdr[i] = off_dat[i] - off_hdr[i] ;
|
||||
if (i==last-1) {
|
||||
qc->dsiz[i] = (sta.st_size/FITS_BLOCK_SIZE) - off_dat[i];
|
||||
} else {
|
||||
qc->dsiz[i] = off_hdr[i+1] - off_dat[i];
|
||||
}
|
||||
}
|
||||
/* Add last modification date */
|
||||
qc->mtime = sta.st_mtime ;
|
||||
qc->ctime = sta.st_ctime ;
|
||||
|
||||
/* Return index of the added file in the cache */
|
||||
return qfits_cache_last ;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,127 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file cache.h
|
||||
@author N. Devillard
|
||||
@date Mar 2001
|
||||
@version $Revision: 1.3 $
|
||||
@brief FITS caching capabilities
|
||||
|
||||
This modules implements a cache for FITS access routines.
|
||||
The first time a FITS file is seen by the library, all corresponding
|
||||
pointers are cached here. This speeds up multiple accesses to large
|
||||
files by magnitudes.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
$Id: cache.h,v 1.3 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.3 $
|
||||
*/
|
||||
|
||||
#ifndef _CACHE_H_
|
||||
#define _CACHE_H_
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** Query the number of extensions */
|
||||
#define QFITS_QUERY_N_EXT (1<<30)
|
||||
/** Query the offset to header start */
|
||||
#define QFITS_QUERY_HDR_START (1<<29)
|
||||
/** Query the offset to data start */
|
||||
#define QFITS_QUERY_DAT_START (1<<28)
|
||||
/** Query header size in bytes */
|
||||
#define QFITS_QUERY_HDR_SIZE (1<<27)
|
||||
/** Query data size in bytes */
|
||||
#define QFITS_QUERY_DAT_SIZE (1<<26)
|
||||
|
||||
|
||||
/* <dox> */
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Purge the qfits cache.
|
||||
@return void
|
||||
|
||||
This function is useful for programs running for a long period,
|
||||
to clean up the cache. Ideally in a daemon, it should be called
|
||||
by a timer at regular intervals. Notice that since the cache is
|
||||
fairly small, you should not need to care too much about this.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_cache_purge(void);
|
||||
/* </dox> */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Query a FITS file offset from the cache.
|
||||
@param filename Name of the file to examine.
|
||||
@param what What should be queried (see below).
|
||||
@return an integer offset, or -1 if an error occurred.
|
||||
|
||||
This function queries the cache for FITS offset information. If the
|
||||
requested file name has never been seen before, it is completely parsed
|
||||
to extract all offset informations, which are then stored in the cache.
|
||||
The next query will get the informations from the cache, avoiding
|
||||
a complete re-parsing of the file. This is especially useful for large
|
||||
FITS files with lots of extensions, because querying the extensions
|
||||
is an expensive operation.
|
||||
|
||||
This operation has side-effects: the cache is an automatically
|
||||
allocated structure in memory, that can only grow. Every request
|
||||
on a new FITS file will make it grow. The structure is pretty
|
||||
light-weight in memory, but nonetheless this is an issue for daemon-type
|
||||
programs which must run over long periods. The solution is to clean
|
||||
the cache using qfits_cache_purge() at regular intervals. This is left
|
||||
to the user of this library.
|
||||
|
||||
To request information about a FITS file, you must pass an integer
|
||||
built from the following symbols:
|
||||
|
||||
- @c QFITS_QUERY_N_EXT
|
||||
- @c QFITS_QUERY_HDR_START
|
||||
- @c QFITS_QUERY_DAT_START
|
||||
- @c QFITS_QUERY_HDR_SIZE
|
||||
- @c QFITS_QUERY_DAT_SIZE
|
||||
|
||||
Querying the number of extensions present in a file is done
|
||||
simply with:
|
||||
|
||||
@code
|
||||
next = qfits_query(filename, QFITS_QUERY_N_EXT);
|
||||
@endcode
|
||||
|
||||
Querying the offset to the i-th extension header is done with:
|
||||
|
||||
@code
|
||||
off = qfits_query(filename, QFITS_QUERY_HDR_START | i);
|
||||
@endcode
|
||||
|
||||
i.e. you must OR (|) the extension number with the
|
||||
@c QFITS_QUERY_HDR_START symbol. Requesting offsets to extension data is
|
||||
done in the same way:
|
||||
|
||||
@code
|
||||
off = qfits_query(filename, QFITS_QUERY_DAT_START | i);
|
||||
@endcode
|
||||
|
||||
Notice that extension 0 is the main header and main data part
|
||||
of the FITS file.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_query(char * filename, int what);
|
||||
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,103 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file expkey.c
|
||||
@author N. Devillard
|
||||
@date Feb 2001
|
||||
@version $Revisions$
|
||||
@brief Expand keyword from shortFITS to HIERARCH notation
|
||||
|
||||
This module offers a function that is reused in a number of different
|
||||
places.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: expkey.c,v 1.4 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.4 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "static_sz.h"
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* Static: uppercase a string */
|
||||
static char * expkey_strupc(char * s)
|
||||
{
|
||||
static char l[ASCIILINESZ+1];
|
||||
int i ;
|
||||
|
||||
if (s==NULL) return NULL ;
|
||||
memset(l, 0, ASCIILINESZ+1);
|
||||
i=0 ;
|
||||
while (s[i] && i<ASCIILINESZ) {
|
||||
l[i] = (char)toupper((int)s[i]);
|
||||
i++ ;
|
||||
}
|
||||
l[ASCIILINESZ]=(char)0;
|
||||
return l ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Expand a keyword from shortFITS to HIERARCH notation.
|
||||
@param keyword Keyword to expand.
|
||||
@return 1 pointer to statically allocated string.
|
||||
|
||||
This function expands a given keyword from shortFITS to HIERARCH
|
||||
notation, bringing it to uppercase at the same time.
|
||||
|
||||
Examples:
|
||||
|
||||
@verbatim
|
||||
det.dit expands to HIERARCH ESO DET DIT
|
||||
ins.filt1.id expands to HIERARCH ESO INS FILT1 ID
|
||||
@endverbatim
|
||||
|
||||
If the input keyword is a regular FITS keyword (i.e. it contains
|
||||
not dots '.') the result is identical to the input.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
char * qfits_expand_keyword(char * keyword)
|
||||
{
|
||||
static char expanded[81];
|
||||
char ws[81];
|
||||
char * token ;
|
||||
|
||||
/* Bulletproof entries */
|
||||
if (keyword==NULL) return NULL ;
|
||||
/* If regular keyword, copy the uppercased input and return */
|
||||
if (strstr(keyword, ".")==NULL) {
|
||||
strcpy(expanded, expkey_strupc(keyword));
|
||||
return expanded ;
|
||||
}
|
||||
/* Regular shortFITS keyword */
|
||||
sprintf(expanded, "HIERARCH ESO");
|
||||
strcpy(ws, expkey_strupc(keyword));
|
||||
token = strtok(ws, ".");
|
||||
while (token!=NULL) {
|
||||
strcat(expanded, " ");
|
||||
strcat(expanded, token);
|
||||
token = strtok(NULL, ".");
|
||||
}
|
||||
return expanded ;
|
||||
}
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file expkey.h
|
||||
@author N. Devillard
|
||||
@date Feb 2001
|
||||
@version $Revisions$
|
||||
@brief Expand keyword from shortFITS to HIERARCH notation
|
||||
|
||||
This module offers a function that is reused in a number of different
|
||||
places.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: expkey.h,v 1.3 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.3 $
|
||||
*/
|
||||
|
||||
#ifndef _EXPKEY_H_
|
||||
#define _EXPKEY_H_
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* <dox> */
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Expand a keyword from shortFITS to HIERARCH notation.
|
||||
@param keyword Keyword to expand.
|
||||
@return 1 pointer to statically allocated string.
|
||||
|
||||
This function expands a given keyword from shortFITS to HIERARCH
|
||||
notation, bringing it to uppercase at the same time.
|
||||
|
||||
Examples:
|
||||
|
||||
@verbatim
|
||||
det.dit expands to HIERARCH ESO DET DIT
|
||||
ins.filt1.id expands to HIERARCH ESO INS FILT1 ID
|
||||
@endverbatim
|
||||
|
||||
If the input keyword is a regular FITS keyword (i.e. it contains
|
||||
not dots '.') the result is identical to the input.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_expand_keyword(char * keyword);
|
||||
/* </dox> */
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,495 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file fits_h.h
|
||||
@author N. Devillard
|
||||
@date Mar 2000
|
||||
@version $Revision: 1.4 $
|
||||
@brief FITS header handling
|
||||
|
||||
This file contains definition and related methods for the FITS header
|
||||
structure. This structure is meant to remain opaque to the user, who
|
||||
only accesses it through the dedicated functions offered in this module.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
$Id: fits_h.h,v 1.4 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.4 $
|
||||
*/
|
||||
|
||||
#ifndef _FITS_HEADER_H_
|
||||
#define _FITS_HEADER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
New types
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/* <dox> */
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief FITS header object
|
||||
|
||||
This structure represents a FITS header in memory. It is actually no
|
||||
more than a thin layer on top of the keytuple object. No field in this
|
||||
structure should be directly modifiable by the user, only through
|
||||
accessor functions.
|
||||
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
typedef struct _qfits_header_ {
|
||||
void * first ; /* Pointer to list start */
|
||||
void * last ; /* Pointer to list end */
|
||||
int n ; /* Number of cards in list */
|
||||
} qfits_header ;
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function ANSI prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief FITS header constructor
|
||||
@return 1 newly allocated (empty) FITS header object.
|
||||
|
||||
This is the main constructor for a qfits_header object. It returns
|
||||
an allocated linked-list handler with an empty card list.
|
||||
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
qfits_header * qfits_header_new(void);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief FITS header default constructor.
|
||||
@return 1 newly allocated qfits_header object.
|
||||
|
||||
This is a secondary constructor for a qfits_header object. It returns
|
||||
an allocated linked-list handler containing two cards: the first one
|
||||
(SIMPLE=T) and the last one (END).
|
||||
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
qfits_header * qfits_header_default(void);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Add a new card to a FITS header
|
||||
@param hdr qfits_header object to modify
|
||||
@param key FITS key
|
||||
@param val FITS value
|
||||
@param com FITS comment
|
||||
@param lin FITS original line if exists
|
||||
@return void
|
||||
|
||||
This function adds a new card into a header, at the one-before-last
|
||||
position, i.e. the entry just before the END entry if it is there.
|
||||
The key must always be a non-NULL string, all other input parameters
|
||||
are allowed to get NULL values.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_header_add(
|
||||
qfits_header * hdr,
|
||||
char * key,
|
||||
char * val,
|
||||
char * com,
|
||||
char * lin);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief add a new card to a FITS header
|
||||
@param hdr qfits_header object to modify
|
||||
@param after Key to specify insertion place
|
||||
@param key FITS key
|
||||
@param val FITS value
|
||||
@param com FITS comment
|
||||
@param lin FITS original line if exists
|
||||
@return void
|
||||
|
||||
Adds a new card to a FITS header, after the specified key. Nothing
|
||||
happens if the specified key is not found in the header. All fields
|
||||
can be NULL, except after and key.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_header_add_after(
|
||||
qfits_header * hdr,
|
||||
char * after,
|
||||
char * key,
|
||||
char * val,
|
||||
char * com,
|
||||
char * lin);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Append a new card to a FITS header.
|
||||
@param hdr qfits_header object to modify
|
||||
@param key FITS key
|
||||
@param val FITS value
|
||||
@param com FITS comment
|
||||
@param lin FITS original line if exists
|
||||
@return void
|
||||
|
||||
Adds a new card in a FITS header as the last one. All fields can be
|
||||
NULL except key.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_header_append(
|
||||
qfits_header * hdr,
|
||||
char * key,
|
||||
char * val,
|
||||
char * com,
|
||||
char * lin);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Delete a card in a FITS header.
|
||||
@param hdr qfits_header to modify
|
||||
@param key specifies which card to remove
|
||||
@return void
|
||||
|
||||
Removes a card from a FITS header. The first found card that matches
|
||||
the key is removed.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_header_del(qfits_header * hdr, char * key);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Modifies a FITS card.
|
||||
@param hdr qfits_header to modify
|
||||
@param key FITS key
|
||||
@param val FITS value
|
||||
@param com FITS comment
|
||||
@return void
|
||||
|
||||
Finds the first card in the header matching 'key', and replaces its
|
||||
value and comment fields by the provided values. The initial FITS
|
||||
line is set to NULL in the card.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_header_mod(qfits_header * hdr, char * key, char * val, char * com);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Updates a given header with another one.
|
||||
@param base Base header to update.
|
||||
@param update Updating header.
|
||||
@return Newly allocated qfits_header object.
|
||||
@doc
|
||||
|
||||
A new header is created from both input headers. It contains:
|
||||
|
||||
- All keywords present in 'base' and not in 'update'.
|
||||
- All keywords present in 'update' and not in 'base'.
|
||||
- All keywords present in both headers with the same value.
|
||||
- In case of conflict (a keyword present in both headers but with
|
||||
different values), the key from the 'update' keyword is used.
|
||||
|
||||
The returned header must be freed using qfits_header_destroy.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
qfits_header * qfits_header_merge(qfits_header * base, qfits_header * update);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Copy a FITS header
|
||||
@param src Header to replicate
|
||||
@return Pointer to newly allocated qfits_header object.
|
||||
|
||||
Makes a strict copy of all information contained in the source
|
||||
header. The returned header must be freed using qfits_header_destroy.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
qfits_header * qfits_header_copy(qfits_header * src);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Touch all cards in a FITS header
|
||||
@param hdr qfits_header to modify
|
||||
@return void
|
||||
|
||||
Touches all cards in a FITS header, i.e. all original FITS lines are
|
||||
freed and set to NULL. Useful when a header needs to be reformatted.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_header_touchall(qfits_header * hdr);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Dump a FITS header to stdout
|
||||
@param hdr qfits_header to dump
|
||||
@return void
|
||||
|
||||
Dump a FITS header to stdout. Mostly for debugging purposes.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_header_consoledump(qfits_header * hdr);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief qfits_header destructor
|
||||
@param hdr qfits_header to deallocate
|
||||
@return void
|
||||
|
||||
Frees all memory associated to a given qfits_header object.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_header_destroy(qfits_header * hdr);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Return the value associated to a key, as a string
|
||||
@param hdr qfits_header to parse
|
||||
@param key key to find
|
||||
@return pointer to statically allocated string
|
||||
|
||||
Finds the value associated to the given key and return it as a
|
||||
string. The returned pointer is statically allocated, so do not
|
||||
modify its contents or try to free it.
|
||||
|
||||
Returns NULL if no matching key is found or no value is attached.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_header_getstr(qfits_header * hdr, char * key);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Find a matching key in a header.
|
||||
@param hdr qfits_header to parse
|
||||
@param key Key prefix to match
|
||||
@return pointer to statically allocated string.
|
||||
|
||||
This function finds the first keyword in the given header for
|
||||
which the given 'key' is a prefix, and returns the full name
|
||||
of the matching key (NOT ITS VALUE). This is useful to locate
|
||||
any keyword starting with a given prefix. Careful with HIERARCH
|
||||
keywords, the shortFITS notation is not likely to be accepted here.
|
||||
|
||||
Examples:
|
||||
|
||||
@verbatim
|
||||
s = qfits_header_findmatch(hdr, "SIMP") returns "SIMPLE"
|
||||
s = qfits_header_findmatch(hdr, "HIERARCH ESO DET") returns
|
||||
the first detector keyword among the HIERACH keys.
|
||||
@endverbatim
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_header_findmatch(qfits_header * hdr, char * key);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Return the i-th key/val/com/line tuple in a header.
|
||||
@param hdr Header to consider
|
||||
@param idx Index of the requested card
|
||||
@param key Output key
|
||||
@param val Output value
|
||||
@param com Output comment
|
||||
@param lin Output initial line
|
||||
@return int 0 if Ok, -1 if error occurred.
|
||||
|
||||
This function is useful to browse a FITS header object card by card.
|
||||
By iterating on the number of cards (available in the 'n' field of
|
||||
the qfits_header struct), you can retrieve the FITS lines and their
|
||||
components one by one. Indexes run from 0 to n-1. You can pass NULL
|
||||
values for key, val, com or lin if you are not interested in a
|
||||
given field.
|
||||
|
||||
@code
|
||||
int i ;
|
||||
char key[80], val[80], com[80], lin[80] ;
|
||||
|
||||
for (i=0 ; i<hdr->n ; i++) {
|
||||
qfits_header_getitem(hdr, i, key, val, com, lin);
|
||||
printf("card[%d] key[%s] val[%s] com[%s]\n", i, key, val, com);
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_header_getitem(
|
||||
qfits_header * hdr,
|
||||
int idx,
|
||||
char * key,
|
||||
char * val,
|
||||
char * com,
|
||||
char * lin
|
||||
);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Return the FITS line associated to a key, as a string
|
||||
@param hdr qfits_header to parse
|
||||
@param key key to find
|
||||
@return pointer to statically allocated string
|
||||
|
||||
Finds the FITS line associated to the given key and return it as a
|
||||
string. The returned pointer is statically allocated, so do not
|
||||
modify its contents or try to free it.
|
||||
|
||||
Returns NULL if no matching key is found or no line is attached.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_header_getline(qfits_header * hdr, char * key);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Return the comment associated to a key, as a string
|
||||
@param hdr qfits_header to parse
|
||||
@param key key to find
|
||||
@return pointer to statically allocated string
|
||||
@doc
|
||||
|
||||
Finds the comment associated to the given key and return it as a
|
||||
string. The returned pointer is statically allocated, so do not
|
||||
modify its contents or try to free it.
|
||||
|
||||
Returns NULL if no matching key is found or no comment is attached.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_header_getcom(qfits_header * hdr, char * key);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Return the value associated to a key, as an int
|
||||
@param hdr qfits_header to parse
|
||||
@param key key to find
|
||||
@param errval default value to return if nothing is found
|
||||
@return int
|
||||
|
||||
Finds the value associated to the given key and return it as an
|
||||
int. Returns errval if no matching key is found or no value is
|
||||
attached.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_header_getint(qfits_header * hdr, char * key, int errval);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Return the value associated to a key, as a double
|
||||
@param hdr qfits_header to parse
|
||||
@param key key to find
|
||||
@param errval default value to return if nothing is found
|
||||
@return double
|
||||
|
||||
Finds the value associated to the given key and return it as a
|
||||
double. Returns errval if no matching key is found or no value is
|
||||
attached.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
double qfits_header_getdouble(qfits_header * hdr, char * key, double errval);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Return the value associated to a key, as a boolean (int).
|
||||
@param hdr qfits_header to parse
|
||||
@param key key to find
|
||||
@param errval default value to return if nothing is found
|
||||
@return int
|
||||
|
||||
Finds the value associated to the given key and return it as a
|
||||
boolean. Returns errval if no matching key is found or no value is
|
||||
attached. A boolean is here understood as an int taking the value 0
|
||||
or 1. errval can be set to any other integer value to reflect that
|
||||
nothing was found.
|
||||
|
||||
errval is returned if no matching key is found or no value is
|
||||
attached.
|
||||
|
||||
A true value is any character string beginning with a 'y' (yes), a
|
||||
't' (true) or the digit '1'. A false value is any character string
|
||||
beginning with a 'n' (no), a 'f' (false) or the digit '0'.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_header_getboolean(qfits_header * hdr, char * key, int errval);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Write out a key tuple to a string on 80 chars.
|
||||
@param line Allocated output character buffer.
|
||||
@param key Key to write.
|
||||
@param val Value to write.
|
||||
@param com Comment to write.
|
||||
@return void
|
||||
|
||||
Write out a key, value and comment into an allocated character buffer.
|
||||
The buffer must be at least 80 chars to receive the information.
|
||||
Formatting is done according to FITS standard.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void keytuple2str(char * line, char * key, char * val, char * com);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Dump a FITS header to an opened file.
|
||||
@param hdr FITS header to dump
|
||||
@param out Opened file pointer
|
||||
@return int 0 if Ok, -1 otherwise
|
||||
|
||||
Dumps a FITS header to an opened file pointer.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_header_dump(qfits_header * hdr, FILE * out);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Dump a fits header into a memory block.
|
||||
@param fh FITS header to dump
|
||||
@param hsize Size of the returned header, in bytes (output).
|
||||
@return 1 newly allocated memory block containing the FITS header.
|
||||
|
||||
This function dumps a FITS header structure into a newly allocated
|
||||
memory block. The block is composed of characters, just as they would
|
||||
appear in a FITS file. This function is useful to make a FITS header
|
||||
in memory.
|
||||
|
||||
The returned block size is indicated in the passed output variable
|
||||
'hsize'. The returned block must be deallocated using free().
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_header_to_memblock(qfits_header * fh, int * hsize);
|
||||
/* </dox> */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,181 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file fits_md5.c
|
||||
@author N. Devillard
|
||||
@date May 2001
|
||||
@version $Revision: 1.4 $
|
||||
@brief FITS data block MD5 computation routine.
|
||||
|
||||
This module offers MD5 computation over all data areas of a FITS file.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: fits_md5.c,v 1.4 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.4 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "md5.h"
|
||||
#include "fits_std.h"
|
||||
#include "qerror.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** Size of an MD5 hash in bytes (32 bytes are 128 bits) */
|
||||
#define MD5HASHSZ 32
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function code
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Compute the MD5 hash of data zones in a FITS file.
|
||||
@param filename Name of the FITS file to examine.
|
||||
@return 1 statically allocated character string, or NULL.
|
||||
|
||||
This function expects the name of a FITS file.
|
||||
It will compute the MD5 hash on all data blocks in the main data section
|
||||
and possibly extensions (including zero-padding blocks if necessary) and
|
||||
return it as a string suitable for inclusion into a FITS keyword.
|
||||
|
||||
The returned string is statically allocated inside this function,
|
||||
so do not free it or modify it. This function returns NULL in case
|
||||
of error.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_datamd5(char * filename)
|
||||
{
|
||||
static char datamd5[MD5HASHSZ+1] ;
|
||||
struct MD5Context ctx ;
|
||||
unsigned char digest[16] ;
|
||||
FILE * in ;
|
||||
char buf[FITS_BLOCK_SIZE];
|
||||
char * buf_c ;
|
||||
int i ;
|
||||
int in_header ;
|
||||
int check_fits ;
|
||||
|
||||
/* Check entries */
|
||||
if (filename==NULL) return NULL ;
|
||||
/* Open input file */
|
||||
if ((in=fopen(filename, "r"))==NULL) {
|
||||
qfits_error("cannot open file %s", filename);
|
||||
return NULL ;
|
||||
}
|
||||
/* Initialize all variables */
|
||||
MD5Init(&ctx);
|
||||
in_header=1 ;
|
||||
check_fits=0 ;
|
||||
/* Loop over input file */
|
||||
while (fread(buf, 1, FITS_BLOCK_SIZE, in)==FITS_BLOCK_SIZE) {
|
||||
/* First time in the loop: check the file is FITS */
|
||||
if (check_fits==0) {
|
||||
/* Examine first characters in block */
|
||||
if (buf[0]!='S' ||
|
||||
buf[1]!='I' ||
|
||||
buf[2]!='M' ||
|
||||
buf[3]!='P' ||
|
||||
buf[4]!='L' ||
|
||||
buf[5]!='E' ||
|
||||
buf[6]!=' ' ||
|
||||
buf[7]!=' ' ||
|
||||
buf[8]!='=') {
|
||||
qfits_error("file [%s] is not FITS\n", filename);
|
||||
fclose(in);
|
||||
return NULL ;
|
||||
} else {
|
||||
check_fits=1 ;
|
||||
}
|
||||
}
|
||||
if (in_header) {
|
||||
buf_c = buf ;
|
||||
for (i=0 ; i<FITS_NCARDS ; i++) {
|
||||
if (buf_c[0]=='E' &&
|
||||
buf_c[1]=='N' &&
|
||||
buf_c[2]=='D' &&
|
||||
buf_c[3]==' ') {
|
||||
in_header=0 ;
|
||||
break ;
|
||||
}
|
||||
buf_c += FITS_LINESZ ;
|
||||
}
|
||||
} else {
|
||||
/* If current block is a data block */
|
||||
/* Try to locate an extension header */
|
||||
if (buf[0]=='X' &&
|
||||
buf[1]=='T' &&
|
||||
buf[2]=='E' &&
|
||||
buf[3]=='N' &&
|
||||
buf[4]=='S' &&
|
||||
buf[5]=='I' &&
|
||||
buf[6]=='O' &&
|
||||
buf[7]=='N' &&
|
||||
buf[8]=='=') {
|
||||
in_header=1 ;
|
||||
buf_c = buf ;
|
||||
for (i=0 ; i<FITS_NCARDS ; i++) {
|
||||
/* Try to find an END marker in this block */
|
||||
if (buf_c[0]=='E' &&
|
||||
buf_c[1]=='N' &&
|
||||
buf_c[2]=='D' &&
|
||||
buf_c[3]==' ') {
|
||||
/* Found END marker in same block as XTENSION */
|
||||
in_header=0;
|
||||
break ;
|
||||
}
|
||||
buf_c += FITS_LINESZ ;
|
||||
}
|
||||
} else {
|
||||
MD5Update(&ctx, (unsigned char *)buf, FITS_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(in);
|
||||
if (check_fits==0) {
|
||||
/* Never went through the read loop: file is not FITS */
|
||||
qfits_error("file [%s] is not FITS", filename);
|
||||
return NULL ;
|
||||
}
|
||||
/* Got to the end of file: summarize */
|
||||
MD5Final(digest, &ctx);
|
||||
/* Write digest into a string */
|
||||
sprintf(datamd5,
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
digest[ 0],
|
||||
digest[ 1],
|
||||
digest[ 2],
|
||||
digest[ 3],
|
||||
digest[ 4],
|
||||
digest[ 5],
|
||||
digest[ 6],
|
||||
digest[ 7],
|
||||
digest[ 8],
|
||||
digest[ 9],
|
||||
digest[10],
|
||||
digest[11],
|
||||
digest[12],
|
||||
digest[13],
|
||||
digest[14],
|
||||
digest[15]);
|
||||
return datamd5 ;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file fits_md5.h
|
||||
@author N. Devillard
|
||||
@date May 2001
|
||||
@version $Revision: 1.3 $
|
||||
@brief FITS data block MD5 computation routine.
|
||||
|
||||
This module offers MD5 computation over all data areas of a FITS file.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: fits_md5.h,v 1.3 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.3 $
|
||||
*/
|
||||
|
||||
#ifndef _FITS_MD5_H_
|
||||
#define _FITS_MD5_H_
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function ANSI prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* <dox> */
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Compute the MD5 hash of data zones in a FITS file.
|
||||
@param filename Name of the FITS file to examine.
|
||||
@return 1 statically allocated character string, or NULL.
|
||||
|
||||
This function expects the name of a FITS file.
|
||||
It will compute the MD5 hash on all data blocks in the main data section
|
||||
and possibly extensions (including zero-padding blocks if necessary) and
|
||||
return it as a string suitable for inclusion into a FITS keyword.
|
||||
|
||||
The returned string is statically allocated inside this function,
|
||||
so do not free it or modify it. This function returns NULL in case
|
||||
of error.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_datamd5(char * filename);
|
||||
/* </dox> */
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,354 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file fits_p.c
|
||||
@author N. Devillard
|
||||
@date Mar 2000
|
||||
@version $Revision: 1.3 $
|
||||
@brief FITS parser for a single card
|
||||
|
||||
This module contains various routines to help parsing a single FITS
|
||||
card into its components: key, value, comment.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: fits_p.c,v 1.3 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.3 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "simple.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* Define the following to get zillions of debug messages */
|
||||
/* #define DEBUG_FITSHEADER */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Find the keyword in a key card (80 chars)
|
||||
@param line allocated 80-char line from a FITS header
|
||||
@return statically allocated char *
|
||||
|
||||
Find out the part of a FITS line corresponding to the keyword.
|
||||
Returns NULL in case of error. The returned pointer is statically
|
||||
allocated in this function, so do not modify or try to free it.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
char * qfits_getkey(char * line)
|
||||
{
|
||||
static char key[81];
|
||||
int i ;
|
||||
|
||||
if (line==NULL) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getkey: NULL input line\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
/* Special case: blank keyword */
|
||||
if (!strncmp(line, " ", 8)) {
|
||||
strcpy(key, " ");
|
||||
return key ;
|
||||
}
|
||||
/*
|
||||
* Sort out special cases: HISTORY, COMMENT and END do not have
|
||||
* equal signs on the line.
|
||||
*/
|
||||
if (!strncmp(line, "HISTORY ", 8)) {
|
||||
strcpy(key, "HISTORY");
|
||||
return key ;
|
||||
}
|
||||
if (!strncmp(line, "COMMENT ", 8)) {
|
||||
strcpy(key, "COMMENT");
|
||||
return key ;
|
||||
}
|
||||
if (!strncmp(line, "END ", 4)) {
|
||||
strcpy(key, "END");
|
||||
return key ;
|
||||
}
|
||||
|
||||
memset(key, 0, 81);
|
||||
/* General case: look for the first equal sign */
|
||||
i=0 ;
|
||||
while (line[i]!='=' && i<80) i++ ;
|
||||
if (i>=80) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getkey: cannot find equal sign\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
i-- ;
|
||||
/* Equal sign found, now backtrack on blanks */
|
||||
while (line[i]==' ' && i>=0) i-- ;
|
||||
if (i<=0) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getkey: error backtracking on blanks\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
i++ ;
|
||||
|
||||
/* Copy relevant characters into output buffer */
|
||||
strncpy(key, line, i) ;
|
||||
/* Null-terminate the string */
|
||||
key[i+1] = (char)0;
|
||||
return key ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Find the value in a key card (80 chars)
|
||||
@param line allocated 80-char line from a FITS header
|
||||
@return statically allocated char *
|
||||
|
||||
Find out the part of a FITS line corresponding to the value.
|
||||
Returns NULL in case of error, or if no value can be found. The
|
||||
returned pointer is statically allocated in this function, so do not
|
||||
modify or try to free it.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
char * qfits_getvalue(char * line)
|
||||
{
|
||||
static char value[81] ;
|
||||
int i ;
|
||||
int from, to ;
|
||||
int inq ;
|
||||
|
||||
if (line==NULL) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getvalue: NULL input line\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
/* Special cases */
|
||||
|
||||
/* END has no associated value */
|
||||
if (!strncmp(line, "END ", 4)) {
|
||||
return NULL ;
|
||||
}
|
||||
/*
|
||||
* HISTORY has for value everything else on the line, stripping
|
||||
* blanks before and after. Blank HISTORY is also accepted.
|
||||
*/
|
||||
memset(value, 0, 81);
|
||||
|
||||
if (!strncmp(line, "HISTORY ", 8) || !strncmp(line, " ", 8)) {
|
||||
i=7 ;
|
||||
/* Strip blanks from the left side */
|
||||
while (line[i]==' ' && i<80) i++ ;
|
||||
if (i>=80) return NULL ; /* Blank HISTORY */
|
||||
from=i ;
|
||||
|
||||
/* Strip blanks from the right side */
|
||||
to=79 ;
|
||||
while (line[to]==' ') to-- ;
|
||||
/* Copy relevant characters into output buffer */
|
||||
strncpy(value, line+from, to-from+1);
|
||||
/* Null-terminate the string */
|
||||
value[to-from+1] = (char)0;
|
||||
return value ;
|
||||
} else if (!strncmp(line, "COMMENT ", 8)) {
|
||||
/*
|
||||
* COMMENT is like HISTORY
|
||||
*/
|
||||
/* Strip blanks from the left side */
|
||||
i=7 ;
|
||||
while (line[i]==' ' && i<80) i++ ;
|
||||
if (i>=80) return NULL ;
|
||||
from=i ;
|
||||
|
||||
/* Strip blanks from the right side */
|
||||
to=79 ;
|
||||
while (line[to]==' ') to-- ;
|
||||
|
||||
if (to<from) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getvalue: inconsistent value search in COMMENT\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
/* Copy relevant characters into output buffer */
|
||||
strncpy(value, line+from, to-from+1);
|
||||
/* Null-terminate the string */
|
||||
value[to-from+1] = (char)0;
|
||||
return value ;
|
||||
}
|
||||
/*
|
||||
* General case
|
||||
* Get past the keyword
|
||||
*/
|
||||
i=0 ;
|
||||
while (line[i]!='=' && i<80) i++ ;
|
||||
if (i>80) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getvalue: no equal sign found on line\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
i++ ;
|
||||
while (line[i]==' ' && i<80) i++ ;
|
||||
if (i>80) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getvalue: no value past the equal sign\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
from=i;
|
||||
|
||||
/*
|
||||
* Now in the value section
|
||||
* Look for the first slash '/' outside of a string
|
||||
*/
|
||||
inq = 0 ;
|
||||
while (i<80) {
|
||||
if (line[i]=='\'')
|
||||
inq=!inq ;
|
||||
if (line[i]=='/')
|
||||
if (!inq)
|
||||
break ;
|
||||
i++;
|
||||
}
|
||||
i-- ;
|
||||
|
||||
/* Backtrack on blanks */
|
||||
while (line[i]==' ' && i>=0) i-- ;
|
||||
if (i<0) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getvalue: error backtracking on blanks\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
to=i ;
|
||||
|
||||
if (to<from) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getvalue: from>to?\n");
|
||||
printf("line=[%s]\n", line);
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
/* Copy relevant characters into output buffer */
|
||||
strncpy(value, line+from, to-from+1);
|
||||
/* Null-terminate the string */
|
||||
value[to-from+1] = (char)0;
|
||||
return value ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Find the comment in a key card (80 chars)
|
||||
@param line allocated 80-char line from a FITS header
|
||||
@return statically allocated char *
|
||||
|
||||
Find out the part of a FITS line corresponding to the comment.
|
||||
Returns NULL in case of error, or if no comment can be found. The
|
||||
returned pointer is statically allocated in this function, so do not
|
||||
modify or try to free it.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
char * qfits_getcomment(char * line)
|
||||
{
|
||||
static char comment[81];
|
||||
int i ;
|
||||
int from, to ;
|
||||
int inq ;
|
||||
|
||||
if (line==NULL) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getcomment: null line in input\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
/* Special cases: END, HISTORY, COMMENT and blank have no comment */
|
||||
if (!strncmp(line, "END ", 4)) return NULL ;
|
||||
if (!strncmp(line, "HISTORY ", 8)) return NULL ;
|
||||
if (!strncmp(line, "COMMENT ", 8)) return NULL ;
|
||||
if (!strncmp(line, " ", 8)) return NULL ;
|
||||
|
||||
memset(comment, 0, 81);
|
||||
/* Get past the keyword */
|
||||
i=0 ;
|
||||
while (line[i]!='=' && i<80) i++ ;
|
||||
if (i>=80) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getcomment: no equal sign on line\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
i++ ;
|
||||
|
||||
/* Get past the value until the slash */
|
||||
inq = 0 ;
|
||||
while (i<80) {
|
||||
if (line[i]=='\'')
|
||||
inq = !inq ;
|
||||
if (line[i]=='/')
|
||||
if (!inq)
|
||||
break ;
|
||||
i++ ;
|
||||
}
|
||||
if (i>=80) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getcomment: no slash found on line\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
i++ ;
|
||||
/* Get past the first blanks */
|
||||
while (line[i]==' ') i++ ;
|
||||
from=i ;
|
||||
|
||||
/*
|
||||
* Now backtrack from the end of the line to the first non-blank
|
||||
* character.
|
||||
*/
|
||||
to=79 ;
|
||||
while (line[to]==' ') to-- ;
|
||||
|
||||
if (to<from) {
|
||||
#ifdef DEBUG_FITSHEADER
|
||||
printf("qfits_getcomment: from>to?\n");
|
||||
#endif
|
||||
return NULL ;
|
||||
}
|
||||
/* Copy relevant characters into output buffer */
|
||||
strncpy(comment, line+from, to-from+1);
|
||||
/* Null-terminate the string */
|
||||
comment[to-from+1] = (char)0;
|
||||
return comment ;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file fits_p.h
|
||||
@author N. Devillard
|
||||
@date Mar 2000
|
||||
@version $Revision: 1.3 $
|
||||
@brief FITS parser for a single card
|
||||
|
||||
This module contains various routines to help parsing a single FITS
|
||||
card into its components: key, value, comment.
|
||||
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: fits_p.h,v 1.3 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.3 $
|
||||
*/
|
||||
|
||||
#ifndef _FITSEP_H_
|
||||
#define _FITSEP_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/* <dox> */
|
||||
/*---------------------------------------------------------------------------
|
||||
Function ANSI C prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Find the keyword in a key card (80 chars)
|
||||
@param line allocated 80-char line from a FITS header
|
||||
@return statically allocated char *
|
||||
|
||||
Find out the part of a FITS line corresponding to the keyword.
|
||||
Returns NULL in case of error. The returned pointer is statically
|
||||
allocated in this function, so do not modify or try to free it.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_getkey(char * line);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Find the value in a key card (80 chars)
|
||||
@param line allocated 80-char line from a FITS header
|
||||
@return statically allocated char *
|
||||
|
||||
Find out the part of a FITS line corresponding to the value.
|
||||
Returns NULL in case of error, or if no value can be found. The
|
||||
returned pointer is statically allocated in this function, so do not
|
||||
modify or try to free it.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_getvalue(char * line);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Find the comment in a key card (80 chars)
|
||||
@param line allocated 80-char line from a FITS header
|
||||
@return statically allocated char *
|
||||
|
||||
Find out the part of a FITS line corresponding to the comment.
|
||||
Returns NULL in case of error, or if no comment can be found. The
|
||||
returned pointer is statically allocated in this function, so do not
|
||||
modify or try to free it.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_getcomment(char * line);
|
||||
/* </dox> */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,309 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file fits_rw.c
|
||||
@author N. Devillard
|
||||
@date Mar 2000
|
||||
@version $Revision: 1.6 $
|
||||
@brief FITS header reading/writing.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: fits_rw.c,v 1.6 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.6 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "fits_rw.h"
|
||||
#include "fits_h.h"
|
||||
#include "fits_p.h"
|
||||
#include "simple.h"
|
||||
#include "xmemory.h"
|
||||
#include "qerror.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private to this module
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static int is_blank_line(char * s)
|
||||
{
|
||||
int i ;
|
||||
|
||||
for (i=0 ; i<(int)strlen(s) ; i++) {
|
||||
if (s[i]!=' ') return 0 ;
|
||||
}
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Read a FITS header from a file to an internal structure.
|
||||
@param filename Name of the file to be read
|
||||
@return Pointer to newly allocated qfits_header
|
||||
|
||||
This function parses a FITS (main) header, and returns an allocated
|
||||
qfits_header object. The qfits_header object contains a linked-list of
|
||||
key "tuples". A key tuple contains:
|
||||
|
||||
- A keyword
|
||||
- A value
|
||||
- A comment
|
||||
- An original FITS line (as read from the input file)
|
||||
|
||||
Direct access to the structure is not foreseen, use accessor
|
||||
functions in fits_h.h
|
||||
|
||||
Value, comment, and original line might be NULL pointers.
|
||||
The qfits_header type is an alias for the llist_t type from the list
|
||||
module, which should remain opaque.
|
||||
|
||||
Returns NULL in case of error.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
qfits_header * qfits_header_read(char * filename)
|
||||
{
|
||||
qfits_header* hdr ;
|
||||
char line[81];
|
||||
char * start ;
|
||||
char * where ;
|
||||
char * key,
|
||||
* val,
|
||||
* com ;
|
||||
size_t fsize ;
|
||||
|
||||
start = falloc(filename, 0, &fsize);
|
||||
if (start==NULL) return NULL ;
|
||||
|
||||
hdr = qfits_header_new();
|
||||
if (hdr==NULL) {
|
||||
free(start);
|
||||
return NULL ;
|
||||
}
|
||||
where = start ;
|
||||
while (1) {
|
||||
memcpy(line, where, 80);
|
||||
line[80] = (char)0;
|
||||
|
||||
/* Rule out blank lines */
|
||||
if (!is_blank_line(line)) {
|
||||
|
||||
/* Get key, value, comment for current line */
|
||||
key = qfits_getkey(line);
|
||||
val = qfits_getvalue(line);
|
||||
com = qfits_getcomment(line);
|
||||
|
||||
/* Any NULL response key triggers an error */
|
||||
if (key==NULL) {
|
||||
qfits_error("in header: cannot read key from\n[%s]", line);
|
||||
qfits_header_destroy(hdr);
|
||||
hdr = NULL ;
|
||||
break ;
|
||||
}
|
||||
|
||||
/* Append current card to linked-list */
|
||||
qfits_header_append(hdr, key, val, com, line);
|
||||
/* Check for END keyword */
|
||||
if (strlen(key)==3)
|
||||
if (key[0]=='E' &&
|
||||
key[1]=='N' &&
|
||||
key[2]=='D')
|
||||
break ;
|
||||
}
|
||||
/* Move out to next line */
|
||||
where += 80 ;
|
||||
/* If reaching the end of the file, trigger an error */
|
||||
if ((int)(where-start)>=(int)(fsize+80)) {
|
||||
qfits_header_destroy(hdr);
|
||||
hdr = NULL ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
free(start);
|
||||
return hdr ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Read an extension header from a FITS file.
|
||||
@param filename Name of the FITS file to read
|
||||
@param xtnum Extension number to read, starting from 1.
|
||||
@return Newly allocated qfits_header structure.
|
||||
|
||||
Strictly similar to qfits_header_read() but reads headers from
|
||||
extensions instead.
|
||||
|
||||
Returns NULL in case of error.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
qfits_header * qfits_header_readext(char * filename, int xtnum)
|
||||
{
|
||||
qfits_header* hdr ;
|
||||
int n_ext ;
|
||||
int hdrstart ;
|
||||
char line[81];
|
||||
char * where ;
|
||||
char * start ;
|
||||
char * key,
|
||||
* val,
|
||||
* com ;
|
||||
size_t fsize ;
|
||||
|
||||
|
||||
/* Check input */
|
||||
if (xtnum<1) return NULL ;
|
||||
|
||||
/* Check that there are enough extensions */
|
||||
n_ext = qfits_query_n_ext(filename);
|
||||
if (xtnum>n_ext) return NULL ;
|
||||
|
||||
/* Get offset to the extension header */
|
||||
if (qfits_get_hdrinfo(filename, xtnum, &hdrstart, NULL)!=0) {
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
/* Memory-map the input file */
|
||||
start = falloc(filename, hdrstart, &fsize) ;
|
||||
if (start==NULL) return NULL ;
|
||||
|
||||
hdr = qfits_header_new() ;
|
||||
where = start ;
|
||||
while (1) {
|
||||
memcpy(line, where, 80);
|
||||
line[80] = (char)0;
|
||||
|
||||
/* Rule out blank lines */
|
||||
if (!is_blank_line(line)) {
|
||||
|
||||
/* Get key, value, comment for the current line */
|
||||
key = qfits_getkey(line);
|
||||
val = qfits_getvalue(line);
|
||||
com = qfits_getcomment(line);
|
||||
|
||||
/* If key or value cannot be found, trigger an error */
|
||||
if (key==NULL) {
|
||||
qfits_header_destroy(hdr);
|
||||
hdr = NULL ;
|
||||
break ;
|
||||
}
|
||||
/* Append card to linked-list */
|
||||
qfits_header_append(hdr, key, val, com, line);
|
||||
/* Check for END keyword */
|
||||
if (strlen(key)==3)
|
||||
if (key[0]=='E' &&
|
||||
key[1]=='N' &&
|
||||
key[2]=='D')
|
||||
break ;
|
||||
}
|
||||
where += 80 ;
|
||||
/* If reaching the end of file, trigger an error */
|
||||
if ((int)(where-start)>=(int)(fsize+80)) {
|
||||
qfits_header_destroy(hdr);
|
||||
hdr = NULL ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
free(start);
|
||||
return hdr ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Pad an existing file with zeros to a multiple of 2880.
|
||||
@param filename Name of the file to pad.
|
||||
@return void
|
||||
|
||||
This function simply pads an existing file on disk with enough zeros
|
||||
for the file size to reach a multiple of 2880, as required by FITS.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void qfits_zeropad(char * filename)
|
||||
{
|
||||
struct stat sta ;
|
||||
int size ;
|
||||
int remaining;
|
||||
FILE * out ;
|
||||
char * buf;
|
||||
|
||||
if (filename==NULL) return ;
|
||||
/* Get file size in bytes */
|
||||
if (stat(filename, &sta)!=0) {
|
||||
return ;
|
||||
}
|
||||
size = (int)sta.st_size ;
|
||||
/* Compute number of zeros to pad */
|
||||
remaining = size % FITS_BLOCK_SIZE ;
|
||||
if (remaining==0) return ;
|
||||
remaining = FITS_BLOCK_SIZE - remaining ;
|
||||
|
||||
/* Open file, dump zeros, exit */
|
||||
if ((out=fopen(filename, "a"))==NULL)
|
||||
return ;
|
||||
buf = calloc(remaining, sizeof(char));
|
||||
fwrite(buf, 1, remaining, out);
|
||||
fclose(out);
|
||||
free(buf);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a file is a FITS file.
|
||||
@param filename name of the file to check
|
||||
@return int 0, 1, or -1
|
||||
|
||||
Returns 1 if the file name looks like a valid FITS file. Returns
|
||||
0 else. If the file does not exist, returns -1.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int is_fits_file(char *filename)
|
||||
{
|
||||
FILE *fp ;
|
||||
char *magic ;
|
||||
int isfits ;
|
||||
|
||||
if (filename==NULL) return -1 ;
|
||||
if ((fp = fopen(filename, "r"))==NULL) {
|
||||
qfits_error("cannot open file [%s]", filename) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
magic = calloc(FITS_MAGIC_SZ+1, sizeof(char)) ;
|
||||
fread(magic, 1, FITS_MAGIC_SZ, fp) ;
|
||||
fclose(fp) ;
|
||||
magic[FITS_MAGIC_SZ] = (char)0 ;
|
||||
if (strstr(magic, FITS_MAGIC)!=NULL)
|
||||
isfits = 1 ;
|
||||
else
|
||||
isfits = 0 ;
|
||||
free(magic) ;
|
||||
return isfits ;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,115 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file fits_rw.h
|
||||
@author N. Devillard
|
||||
@date Mar 2000
|
||||
@version $Revision: 1.4 $
|
||||
@brief FITS header reading/writing.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: fits_rw.h,v 1.4 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.4 $
|
||||
*/
|
||||
|
||||
#ifndef _FITS_RW_H_
|
||||
#define _FITS_RW_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fits_std.h"
|
||||
#include "fits_h.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function ANSI prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* <dox> */
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Read a FITS header from a file to an internal structure.
|
||||
@param filename Name of the file to be read
|
||||
@return Pointer to newly allocated qfits_header
|
||||
|
||||
This function parses a FITS (main) header, and returns an allocated
|
||||
qfits_header object. The qfits_header object contains a linked-list of
|
||||
key "tuples". A key tuple contains:
|
||||
|
||||
- A keyword
|
||||
- A value
|
||||
- A comment
|
||||
- An original FITS line (as read from the input file)
|
||||
|
||||
Direct access to the structure is not foreseen, use accessor
|
||||
functions in fits_h.h
|
||||
|
||||
Value, comment, and original line might be NULL pointers.
|
||||
The qfits_header type is an alias for the llist_t type from the list
|
||||
module, which should remain opaque.
|
||||
|
||||
Returns NULL in case of error.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
qfits_header * qfits_header_read(char * filename);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Read an extension header from a FITS file.
|
||||
@param filename Name of the FITS file to read
|
||||
@param xtnum Extension number to read, starting from 1.
|
||||
@return Newly allocated qfits_header structure.
|
||||
|
||||
Strictly similar to fits_read_header() but reads headers from
|
||||
extensions instead.
|
||||
|
||||
Returns NULL in case of error.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
qfits_header * qfits_header_readext(char * filename, int xtnum);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Pad an existing file with zeros to a multiple of 2880.
|
||||
@param filename Name of the file to pad.
|
||||
@return void
|
||||
|
||||
This function simply pads an existing file on disk with enough zeros
|
||||
for the file size to reach a multiple of 2880, as required by FITS.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_zeropad(char * filename);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a file is a FITS file.
|
||||
@param filename name of the file to check
|
||||
@return int 0, 1, or -1
|
||||
|
||||
Returns 1 if the file name looks like a valid FITS file. Returns
|
||||
0 else. If the file does not exist, returns -1.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int is_fits_file(char *filename);
|
||||
|
||||
/* </dox> */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,74 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file fits_std.h
|
||||
@author N. Devillard
|
||||
@date November 2001
|
||||
@version $Revision: 1.3 $
|
||||
@brief
|
||||
|
||||
This header file gathers a number of definitions strictly related
|
||||
to the FITS format. Include it if you need to get definitions for
|
||||
a FITS line size, header metrics, and other FITS-only symbols.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: fits_std.h,v 1.3 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.3 $
|
||||
*/
|
||||
|
||||
#ifndef _FITS_STD_H_
|
||||
#define _FITS_STD_H_
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* <dox> */
|
||||
/* FITS header constants */
|
||||
|
||||
/** FITS block size */
|
||||
#define FITS_BLOCK_SIZE (2880)
|
||||
/** FITS number of cards per block */
|
||||
#define FITS_NCARDS (36)
|
||||
/** FITS size of each line in bytes */
|
||||
#define FITS_LINESZ (80)
|
||||
|
||||
/** FITS magic number */
|
||||
#define FITS_MAGIC "SIMPLE"
|
||||
/** Size of the FITS magic number */
|
||||
#define FITS_MAGIC_SZ 6
|
||||
|
||||
|
||||
|
||||
|
||||
/* FITS pixel depths */
|
||||
|
||||
/** FITS BITPIX=8 */
|
||||
#define BPP_8_UNSIGNED (8)
|
||||
/** FITS BITPIX=16 */
|
||||
#define BPP_16_SIGNED (16)
|
||||
/** FITS BITPIX=32 */
|
||||
#define BPP_32_SIGNED (32)
|
||||
/** FITS BITPIX=-32 */
|
||||
#define BPP_IEEE_FLOAT (-32)
|
||||
/** FITS BITPIX=-64 */
|
||||
#define BPP_IEEE_DOUBLE (-64)
|
||||
|
||||
/** Default BITPIX for output */
|
||||
#define BPP_DEFAULT BPP_IEEE_FLOAT
|
||||
|
||||
/** Compute the number of bytes per pixel for a given BITPIX value */
|
||||
#define BYTESPERPIXEL(x) ( ((x) == BPP_8_UNSIGNED) ? 1 : \
|
||||
((x) == BPP_16_SIGNED) ? 2 : \
|
||||
((x) == BPP_32_SIGNED) ? 4 : \
|
||||
((x) == BPP_IEEE_FLOAT) ? 4 : \
|
||||
((x) == BPP_IEEE_DOUBLE) ? 8 : 0 )
|
||||
|
||||
|
||||
/* </dox> */
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
#include "md5.h"
|
||||
#include <string.h> /* To get definition of memmove */
|
||||
|
||||
static void byteReverse(unsigned char *buf, unsigned longs);
|
||||
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
*/
|
||||
static void byteReverse(unsigned char *buf, unsigned longs)
|
||||
{
|
||||
word32 t;
|
||||
do {
|
||||
t = (word32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(word32 *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void MD5Init(struct MD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
|
||||
{
|
||||
register word32 t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((word32) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t) {
|
||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t) {
|
||||
memmove(p, buf, len);
|
||||
return;
|
||||
}
|
||||
memmove(p, buf, t);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (word32 *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64) {
|
||||
memmove(ctx->in, buf, 64);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (word32 *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
|
||||
memmove(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
|
||||
{
|
||||
unsigned int count;
|
||||
unsigned char *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset(p, 0, count);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (word32 *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(ctx->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((word32 *) ctx->in)[14] = ctx->bits[0];
|
||||
((word32 *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform(ctx->buf, (word32 *) ctx->in);
|
||||
byteReverse((unsigned char *) ctx->buf, 4);
|
||||
memmove(digest, ctx->buf, 16);
|
||||
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
void MD5Transform(word32 buf[4], word32 const in[16])
|
||||
{
|
||||
register word32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
typedef unsigned int word32 ;
|
||||
|
||||
|
||||
struct MD5Context {
|
||||
word32 buf[4];
|
||||
word32 bits[2];
|
||||
unsigned char in[64];
|
||||
};
|
||||
|
||||
void MD5Init(struct MD5Context *context);
|
||||
void MD5Update(struct MD5Context *context, unsigned char const *buf,
|
||||
unsigned len);
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *context);
|
||||
void MD5Transform(word32 buf[4], word32 const in[16]);
|
||||
|
||||
/*
|
||||
* This is needed to make RSAREF happy on some MS-DOS compilers.
|
||||
*/
|
||||
typedef struct MD5Context MD5_CTX;
|
||||
|
||||
#endif /* !MD5_H */
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,465 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file pixload.h
|
||||
@author N. Devillard
|
||||
@date Nov 2001
|
||||
@version $Revision: 1.3 $
|
||||
@brief Pixel loader for FITS images.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: pixio.h,v 1.3 2002/01/21 15:23:52 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/21 15:23:52 $
|
||||
$Revision: 1.3 $
|
||||
*/
|
||||
|
||||
#ifndef _PIXLOAD_H_
|
||||
#define _PIXLOAD_H_
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xmemory.h"
|
||||
|
||||
|
||||
/* <dox> */
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** Symbol to set returned pixel type to float */
|
||||
#define PTYPE_FLOAT 0
|
||||
/** Symbol to set returned pixel type to int */
|
||||
#define PTYPE_INT 1
|
||||
/** Symbol to set returned pixel type to double */
|
||||
#define PTYPE_DOUBLE 2
|
||||
|
||||
/** FITS BITPIX=8 */
|
||||
#define BPP_8_UNSIGNED (8)
|
||||
/** FITS BITPIX=16 */
|
||||
#define BPP_16_SIGNED (16)
|
||||
/** FITS BITPIX=32 */
|
||||
#define BPP_32_SIGNED (32)
|
||||
/** FITS BITPIX=-32 */
|
||||
#define BPP_IEEE_FLOAT (-32)
|
||||
/** FITS BITPIX=-64 */
|
||||
#define BPP_IEEE_DOUBLE (-64)
|
||||
|
||||
/** Default BITPIX for output */
|
||||
#define BPP_DEFAULT BPP_IEEE_FLOAT
|
||||
|
||||
/** Compute the number of bytes per pixel for a given BITPIX value */
|
||||
#define BYTESPERPIXEL(x) ( ((x) == BPP_8_UNSIGNED) ? 1 : \
|
||||
((x) == BPP_16_SIGNED) ? 2 : \
|
||||
((x) == BPP_32_SIGNED) ? 4 : \
|
||||
((x) == BPP_IEEE_FLOAT) ? 4 : \
|
||||
((x) == BPP_IEEE_DOUBLE) ? 8 : 0 )
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
New types
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief qfits loader control object
|
||||
|
||||
This structure serves two purposes: input and output for the qfits
|
||||
pixel loading facility. To request pixels from a FITS file, you
|
||||
need to allocate (statically or dynamically) such a structure and
|
||||
fill up the input fields (filename, xtension number, etc.) to specify
|
||||
the pixels you want from the file.
|
||||
|
||||
Before performing the actual load, you must pass the initialized
|
||||
structure to qfitsloader_init() which will check whether the operation
|
||||
is feasible or not (check its returned value).
|
||||
|
||||
If the operation was deemed feasible, you can proceed to load the pixels,
|
||||
passing the same structure to qfits_loadpix() which will fill up the
|
||||
output fields of the struct. Notice that a pixel buffer will have been
|
||||
allocated (through malloc or mmap) and placed into the structure. You
|
||||
need to call free() on this pointer when you are done with it,
|
||||
typically in the image or cube destructor.
|
||||
|
||||
The qfitsloader_init() function is also useful to probe a FITS file
|
||||
for useful informations, like getting the size of images in the file,
|
||||
the pixel depth, or data offset.
|
||||
|
||||
Example of a code that prints out various informations about
|
||||
a plane to load, without actually loading it:
|
||||
|
||||
@code
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
qfitsloader ql ;
|
||||
|
||||
ql.filename = argv[1] ;
|
||||
ql.xtnum = 0 ;
|
||||
ql.pnum = 0 ;
|
||||
|
||||
if (qfitsloader_init(&ql)!=0) {
|
||||
printf("cannot read info about %s\n", argv[1]);
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
printf( "file : %s"
|
||||
"xtnum : %d"
|
||||
"pnum : %d"
|
||||
"# xtensions : %d"
|
||||
"size X : %d"
|
||||
"size Y : %d"
|
||||
"planes : %d"
|
||||
"bitpix : %d"
|
||||
"datastart : %d"
|
||||
"bscale : %g"
|
||||
"bzero : %g",
|
||||
ql.filename,
|
||||
ql.xtnum,
|
||||
ql.pnum,
|
||||
ql.exts,
|
||||
ql.lx,
|
||||
ql.ly,
|
||||
ql.np,
|
||||
ql.bitpix,
|
||||
ql.seg_start,
|
||||
ql.bscale,
|
||||
ql.bzero);
|
||||
return 0 ;
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
typedef struct _qfitsloader_ {
|
||||
|
||||
/** Private field to see if structure has been initialized */
|
||||
int _init ;
|
||||
|
||||
/** input: Name of the file you want to read pixels from */
|
||||
char * filename ;
|
||||
/** input: xtension number you want to read */
|
||||
int xtnum ;
|
||||
/** input: Index of the plane you want, from 0 to np-1 */
|
||||
int pnum ;
|
||||
/** input: Pixel type you want (PTYPE_FLOAT, PTYPE_INT or PTYPE_DOUBLE) */
|
||||
int ptype ;
|
||||
|
||||
/** output: Total number of extensions found in file */
|
||||
int exts ;
|
||||
/** output: Size in X of the requested plane */
|
||||
int lx ;
|
||||
/** output: Size in Y of the requested plane */
|
||||
int ly ;
|
||||
/** output: Number of planes present in this extension */
|
||||
int np ;
|
||||
/** output: BITPIX for this extension */
|
||||
int bitpix ;
|
||||
/** output: Start of the data segment (in bytes) for your request */
|
||||
int seg_start ;
|
||||
/** output: BSCALE found for this extension */
|
||||
double bscale ;
|
||||
/** output: BZERO found for this extension */
|
||||
double bzero ;
|
||||
|
||||
/** output: Pointer to pixel buffer loaded as integer values */
|
||||
int * ibuf ;
|
||||
/** output: Pointer to pixel buffer loaded as float values */
|
||||
float * fbuf ;
|
||||
/** output: Pointer to pixel buffer loaded as double values */
|
||||
double * dbuf ;
|
||||
|
||||
} qfitsloader ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief qfits dumper control object
|
||||
|
||||
This structure offers various control parameters to dump a pixel
|
||||
buffer to a FITS file. The buffer will be dumped as requested
|
||||
to the requested file in append mode. Of course, the requested file
|
||||
must be writeable for the operation to succeed.
|
||||
|
||||
The following example demonstrates how to save a linear ramp sized
|
||||
100x100 to a FITS file with BITPIX=16. Notice that this code only
|
||||
dumps the pixel buffer, no header information is provided in this
|
||||
case.
|
||||
|
||||
@code
|
||||
int i, j ;
|
||||
int * ibuf ;
|
||||
qfitsdumper qd ;
|
||||
|
||||
// Fill a buffer with 100x100 int pixels
|
||||
ibuf = malloc(100 * 100 * sizeof(int));
|
||||
for (j=0 ; j<100 ; j++) {
|
||||
for (i=0 ; i<100 ; i++) {
|
||||
ibuf[i+j*100] = i+j ;
|
||||
}
|
||||
}
|
||||
|
||||
qd.filename = "out.fits" ; // Output file name
|
||||
qd.npix = 100 * 100 ; // Number of pixels
|
||||
qd.ptype = PTYPE_INT ; // Input buffer type
|
||||
qd.ibuf = ibuf ; // Set buffer pointer
|
||||
qd.out_ptype = BPP_16_SIGNED ; // Save with BITPIX=16
|
||||
|
||||
// Dump buffer to file (error checking omitted for clarity)
|
||||
qfits_pixdump(&qd);
|
||||
|
||||
free(ibuf);
|
||||
@endcode
|
||||
|
||||
If the provided output file name is "STDOUT" (all capitals), the
|
||||
function will dump the pixels to the stdout steam (usually the console,
|
||||
could have been re-directed).
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
typedef struct _qfitsdumper_ {
|
||||
|
||||
/** Name of the file to dump to, "STDOUT" to dump to stdout */
|
||||
char * filename ;
|
||||
/** Number of pixels in the buffer to dump */
|
||||
int npix ;
|
||||
/** Buffer type: PTYPE_FLOAT, PTYPE_INT or PTYPE_DOUBLE */
|
||||
int ptype ;
|
||||
|
||||
/** Pointer to input integer pixel buffer */
|
||||
int * ibuf ;
|
||||
/** Pointer to input float pixel buffer */
|
||||
float * fbuf ;
|
||||
/** Pointer to input double pixel buffer */
|
||||
double * dbuf ;
|
||||
|
||||
/** Requested BITPIX in output FITS file */
|
||||
int out_ptype ;
|
||||
} qfitsdumper ;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Initialize a qfitsloader control object.
|
||||
@param ql qfitsloader object to initialize.
|
||||
@return int 0 if Ok, -1 if error occurred.
|
||||
|
||||
This function expects a qfitsloader object with a number of input
|
||||
fields correctly filled in. The minimum fields to set are:
|
||||
|
||||
- filename: Name of the file to examine.
|
||||
- xtnum: Extension number to examine (0 for main section).
|
||||
- pnum: Plane number in the requested extension.
|
||||
|
||||
You can go ahead with these fields only if you only want to get
|
||||
file information for this plane in this extension. If you want
|
||||
to later load the plane, you must additionally fill the 'ptype'
|
||||
field to a correct value (PTYPE_INT, PTYPE_FLOAT, PTYPE_DOUBLE)
|
||||
before calling qfits_loadpix() so that it knows which conversion
|
||||
to perform.
|
||||
|
||||
This function is basically a probe sent on a FITS file to ask
|
||||
qfits if loading these data would be Ok or not. The actual loading
|
||||
is performed by qfits_loadpix() afterwards.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfitsloader_init(qfitsloader * ql);
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Load a pixel buffer for one image.
|
||||
@param ql Allocated and initialized qfitsloader control object.
|
||||
@return int 0 if Ok, -1 if error occurred.
|
||||
|
||||
This function performs a load of a pixel buffer into memory. It
|
||||
expects an allocated and initialized qfitsloader object in input.
|
||||
See qfitsloader_init() about initializing the object.
|
||||
|
||||
This function will fill up the ibuf/fbuf/dbuf field, depending
|
||||
on the requested pixel type (resp. int, float or double).
|
||||
|
||||
The returned buffer has been allocated using one of the special
|
||||
memory operators present in xmemory.c. To deallocate the buffer,
|
||||
you must call the version of free() offered by xmemory, not the
|
||||
usual system free(). It is enough to include "xmemory.h" in your
|
||||
code before you make calls to the pixel loader here.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_loadpix(qfitsloader * ql);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Load a pixel buffer as floats.
|
||||
@param p_source Pointer to source buffer (as bytes).
|
||||
@param npix Number of pixels to load.
|
||||
@param bitpix FITS BITPIX in original file.
|
||||
@param bscale FITS BSCALE in original file.
|
||||
@param bzero FITS BZERO in original file.
|
||||
@return 1 pointer to a newly allocated buffer of npix floats.
|
||||
|
||||
This function takes in input a pointer to a byte buffer as given
|
||||
in the original FITS file (big-endian format). It converts the
|
||||
buffer to an array of float (whatever representation is used for
|
||||
floats by this platform is used) and returns the newly allocated
|
||||
buffer, or NULL if an error occurred.
|
||||
|
||||
The returned buffer must be deallocated using the free() offered
|
||||
by xmemory. It is enough to #include "xmemory.h" before calling
|
||||
free on the returned pointer.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
float * qfits_pixin_float (char *, int, int, double, double);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Load a pixel buffer as ints.
|
||||
@param p_source Pointer to source buffer (as bytes).
|
||||
@param npix Number of pixels to load.
|
||||
@param bitpix FITS BITPIX in original file.
|
||||
@param bscale FITS BSCALE in original file.
|
||||
@param bzero FITS BZERO in original file.
|
||||
@return 1 pointer to a newly allocated buffer of npix ints.
|
||||
|
||||
This function takes in input a pointer to a byte buffer as given
|
||||
in the original FITS file (big-endian format). It converts the
|
||||
buffer to an array of int (whatever representation is used for
|
||||
int by this platform is used) and returns the newly allocated
|
||||
buffer, or NULL if an error occurred.
|
||||
|
||||
The returned buffer must be deallocated using the free() offered
|
||||
by xmemory. It is enough to #include "xmemory.h" before calling
|
||||
free on the returned pointer.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int * qfits_pixin_int (char *, int, int, double, double);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Load a pixel buffer as doubles.
|
||||
@param p_source Pointer to source buffer (as bytes).
|
||||
@param npix Number of pixels to load.
|
||||
@param bitpix FITS BITPIX in original file.
|
||||
@param bscale FITS BSCALE in original file.
|
||||
@param bzero FITS BZERO in original file.
|
||||
@return 1 pointer to a newly allocated buffer of npix doubles.
|
||||
|
||||
This function takes in input a pointer to a byte buffer as given
|
||||
in the original FITS file (big-endian format). It converts the
|
||||
buffer to an array of double (whatever representation is used for
|
||||
int by this platform is used) and returns the newly allocated
|
||||
buffer, or NULL if an error occurred.
|
||||
|
||||
The returned buffer must be deallocated using the free() offered
|
||||
by xmemory. It is enough to #include "xmemory.h" before calling
|
||||
free on the returned pointer.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
double * qfits_pixin_double(char *, int, int, double, double);
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Dump a pixel buffer to an output FITS file in append mode.
|
||||
@param qd qfitsdumper control object.
|
||||
@return int 0 if Ok, -1 otherwise.
|
||||
|
||||
This function takes in input a qfitsdumper control object. This object
|
||||
must be allocated beforehand and contain valid references to the data
|
||||
to save, and how to save it.
|
||||
|
||||
The minimum fields to fill are:
|
||||
|
||||
- filename: Name of the FITS file to dump to.
|
||||
- npix: Number of pixels in the buffer to be dumped.
|
||||
- ptype: Type of the passed buffer (PTYPE_FLOAT, PTYPE_INT, PTYPE_DOUBLE)
|
||||
- out_ptype: Requested FITS BITPIX for the output.
|
||||
|
||||
One of the following fields must point to the corresponding pixel
|
||||
buffer:
|
||||
|
||||
- ibuf for an int pixel buffer (ptype=PTYPE_INT)
|
||||
- fbuf for a float pixel buffer (ptype=PTYPE_FLOAT)
|
||||
- dbuf for a double pixel buffer (ptype=PTYPE_DOUBLE)
|
||||
|
||||
This is a fairly low-level function, in the sense that it does not
|
||||
check that the output file already contains a proper header or even
|
||||
that the file it is appending to is indeed a FITS file. It will
|
||||
convert the pixel buffer to the requested BITPIX type and append
|
||||
the data to the file, without padding with zeros. See qfits_zeropad()
|
||||
about padding.
|
||||
|
||||
If the given output file name is "STDOUT" (all caps), the dump
|
||||
will be performed to stdout.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_pixdump(qfitsdumper * qd) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Convert a float pixel buffer to a byte buffer.
|
||||
@param buf Input float buffer.
|
||||
@param npix Number of pixels in the input buffer.
|
||||
@param ptype Requested output BITPIX type.
|
||||
@return 1 pointer to a newly allocated byte (char) buffer.
|
||||
|
||||
This function converts the given float buffer to a buffer of bytes
|
||||
suitable for dumping to a FITS file (i.e. big-endian, in the
|
||||
requested pixel type). The returned pointer must be deallocated
|
||||
using the free() function offered by xmemory.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_pixdump_float(float * buf, int npix, int ptype);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Convert an int pixel buffer to a byte buffer.
|
||||
@param buf Input int buffer.
|
||||
@param npix Number of pixels in the input buffer.
|
||||
@param ptype Requested output BITPIX type.
|
||||
@return 1 pointer to a newly allocated byte (char) buffer.
|
||||
|
||||
This function converts the given int buffer to a buffer of bytes
|
||||
suitable for dumping to a FITS file (i.e. big-endian, in the
|
||||
requested pixel type). The returned pointer must be deallocated
|
||||
using the free() function offered by xmemory.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_pixdump_int(int * buf, int npix, int ptype);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Convert a double pixel buffer to a byte buffer.
|
||||
@param buf Input double buffer.
|
||||
@param npix Number of pixels in the input buffer.
|
||||
@param ptype Requested output BITPIX type.
|
||||
@return 1 pointer to a newly allocated byte (char) buffer.
|
||||
|
||||
This function converts the given double buffer to a buffer of bytes
|
||||
suitable for dumping to a FITS file (i.e. big-endian, in the
|
||||
requested pixel type). The returned pointer must be deallocated
|
||||
using the free() function offered by xmemory.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_pixdump_double(double * buf, int npix, int ptype);
|
||||
|
||||
/* </dox> */
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,123 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file ptrace.c
|
||||
@author N. Devillard
|
||||
@date May 2001
|
||||
@version $Revision: 2.6 $
|
||||
@brief Add tracing capability to any program compiled with gcc.
|
||||
|
||||
This module is only compiled when using gcc and tracing has been
|
||||
activated. It allows the compiled program to output messages whenever
|
||||
a function is entered or exited.
|
||||
|
||||
To activate this feature, your version of gcc must support
|
||||
the -finstrument-functions flag.
|
||||
|
||||
The printed messages yield function addresses, not human-readable
|
||||
names. To link both, you need to get a list of symbols from the
|
||||
program. There are many (unportable) ways of doing that, see the
|
||||
'etrace' project on freshmeat for more information about how to dig
|
||||
the information.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: ptrace.c,v 2.6 2002/01/22 14:52:40 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/22 14:52:40 $
|
||||
$Revision: 2.6 $
|
||||
*/
|
||||
|
||||
#if (__GNUC__>2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ > 95))
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#define PTRACE_PIPENAME "TRACE"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/** Final trace close */
|
||||
static void
|
||||
__attribute__((__no_instrument_function__))
|
||||
gnu_ptrace_close(void)
|
||||
{
|
||||
FILE * trace ;
|
||||
if ((trace=fopen(PTRACE_PIPENAME, "a"))==NULL) return ;
|
||||
fprintf(trace, "EXIT %ld\n", (long)getpid());
|
||||
fclose(trace);
|
||||
return ;
|
||||
}
|
||||
|
||||
/** Trace initialization */
|
||||
static int
|
||||
__attribute__((__no_instrument_function__))
|
||||
gnu_ptrace_init(void)
|
||||
{
|
||||
struct stat sta ;
|
||||
|
||||
/* See if a trace file exists */
|
||||
if (stat(PTRACE_PIPENAME, &sta)!=0) {
|
||||
/* No trace file: do not trace at all */
|
||||
return 0 ;
|
||||
}
|
||||
/* Tracing requested: a trace file was found */
|
||||
atexit(gnu_ptrace_close);
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
/** Function called by every function event */
|
||||
void
|
||||
__attribute__((__no_instrument_function__))
|
||||
gnu_ptrace(char * what, void * p)
|
||||
{
|
||||
static int first=1 ;
|
||||
static int active=1 ;
|
||||
FILE * trace ;
|
||||
|
||||
if (first) {
|
||||
active = gnu_ptrace_init();
|
||||
first=0 ;
|
||||
}
|
||||
if (active==0)
|
||||
return ;
|
||||
|
||||
if ((trace=fopen(PTRACE_PIPENAME, "a"))==NULL) {
|
||||
return ;
|
||||
}
|
||||
fprintf(trace, "%s %p\n", what, p);
|
||||
fclose(trace);
|
||||
return ;
|
||||
}
|
||||
|
||||
/** According to gcc documentation: called upon function entry */
|
||||
void __attribute__((__no_instrument_function__))
|
||||
__cyg_profile_func_enter(void *this_fn, void *call_site)
|
||||
{
|
||||
gnu_ptrace("enter", this_fn);
|
||||
}
|
||||
|
||||
/** According to gcc documentation: called upon function exit */
|
||||
void __attribute__((__no_instrument_function__))
|
||||
__cyg_profile_func_exit(void *this_fn, void *call_site)
|
||||
{
|
||||
gnu_ptrace("exit", this_fn);
|
||||
}
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,217 @@
|
|||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file qerror.c
|
||||
@author N. Devillard
|
||||
@date Aug 2001
|
||||
@version $Revision: 1.5 $
|
||||
@brief
|
||||
|
||||
This module is responsible for error message display. It allows
|
||||
to re-direct all messages to a given set of functions for display.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: qerror.c,v 1.5 2002/01/15 10:18:38 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/15 10:18:38 $
|
||||
$Revision: 1.5 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
/* Max number of error handling functions registered */
|
||||
#define QFITS_ERR_MAXERRDISP 8
|
||||
|
||||
/* Max size of an error message */
|
||||
#define QFITS_ERR_MSGSIZE 1024
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private stuff
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* Type of a display function only defined for legibility here */
|
||||
typedef void (*qfits_err_dispfunc)(char *) ;
|
||||
|
||||
/* Default display function prints out msg to stderr */
|
||||
static void qfits_err_display_stderr(char * s)
|
||||
{ fprintf(stderr, "qfits: %s\n", s); }
|
||||
|
||||
/* Static control structure, completely private */
|
||||
static struct {
|
||||
qfits_err_dispfunc disp[QFITS_ERR_MAXERRDISP] ;
|
||||
int n ;
|
||||
int active ;
|
||||
} qfits_err_control = {{qfits_err_display_stderr}, 1, 1} ;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Private: this is the main function used for message display.
|
||||
* It calls registered display functions one after another.
|
||||
*/
|
||||
static void qfits_err_main_display(char * msg)
|
||||
{
|
||||
int i ;
|
||||
|
||||
/* Check if there is a message in input */
|
||||
if (msg==NULL)
|
||||
return ;
|
||||
|
||||
/* Loop on all registered functions and call them */
|
||||
for (i=0 ; i<qfits_err_control.n ; i++) {
|
||||
if (qfits_err_control.disp[i]) {
|
||||
qfits_err_control.disp[i](msg);
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name qfits_err_statget
|
||||
@memo Get the current status of error display.
|
||||
@return int 1 if error display is active, 0 if not.
|
||||
@doc
|
||||
|
||||
This function returns the current error display status. If it returns 1,
|
||||
it means that all calls to qfits_error/qfits_warning will display
|
||||
messages using the registered functions, otherwise they do nothing.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_err_statget(void)
|
||||
{
|
||||
return qfits_err_control.active ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name qfits_err_statset
|
||||
@memo Set the current status of error display.
|
||||
@param sta New status to be set.
|
||||
@return int giving the previous display status.
|
||||
@doc
|
||||
|
||||
This function sets the current error display status to the required
|
||||
value, and returns the previous value. It is useful to store the
|
||||
previous value, in view of restoring it afterwards, e.g. to make a
|
||||
function silent on all its errors. Example:
|
||||
|
||||
@code
|
||||
int prev_stat = qfits_err_statset(0) ;
|
||||
function_call() ;
|
||||
qfits_err_statset(prev_stat);
|
||||
@endcode
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_err_statset(int sta)
|
||||
{
|
||||
int prev ;
|
||||
prev = qfits_err_control.active ;
|
||||
qfits_err_control.active=sta ;
|
||||
return prev ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name qfits_err_register
|
||||
@memo Register a function to display error/warning messages.
|
||||
@param dispfn Display function (see doc below).
|
||||
@return int 0 if function was registered, -1 if not.
|
||||
@doc
|
||||
|
||||
This function registers a display function into the error-handling
|
||||
module. Display functions have the following prototype:
|
||||
|
||||
@code
|
||||
void display_function(char * msg);
|
||||
@endcode
|
||||
|
||||
They are simple functions that expect a ready-made error message
|
||||
and return void. They can do whatever they want with the message
|
||||
(log it to a file, send it to a GUI, to the syslog, ...). The
|
||||
message is built using a printf-like statement in qfits_error and
|
||||
qfits_warning, then passed to all registered display functions.
|
||||
|
||||
A maximum of QFITS_ERR_MAXERRDISP can be registered (see source code).
|
||||
If the limit has been reached, this function will signal it by
|
||||
returning -1.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int qfits_err_register(qfits_err_dispfunc dispfn)
|
||||
{
|
||||
if (qfits_err_control.n==QFITS_ERR_MAXERRDISP) {
|
||||
/* Cannot register any more function */
|
||||
return -1 ;
|
||||
}
|
||||
qfits_err_control.disp[qfits_err_control.n] = dispfn ;
|
||||
qfits_err_control.n ++ ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Public warning/error functions */
|
||||
void qfits_warning(char *fmt, ...)
|
||||
{
|
||||
char msg[QFITS_ERR_MSGSIZE] ;
|
||||
char all[QFITS_ERR_MSGSIZE] ;
|
||||
va_list ap ;
|
||||
|
||||
/* Check if display is activated */
|
||||
if (qfits_err_control.active==0) {
|
||||
return ;
|
||||
}
|
||||
va_start(ap, fmt) ;
|
||||
vsprintf(msg, fmt, ap) ;
|
||||
va_end(ap);
|
||||
|
||||
sprintf(all, "*** %s", msg);
|
||||
qfits_err_main_display(all);
|
||||
return ;
|
||||
}
|
||||
|
||||
void qfits_error(char *fmt, ...)
|
||||
{
|
||||
char msg[QFITS_ERR_MSGSIZE] ;
|
||||
char all[QFITS_ERR_MSGSIZE] ;
|
||||
va_list ap ;
|
||||
|
||||
/* Check if display is activated */
|
||||
if (qfits_err_control.active==0) {
|
||||
return ;
|
||||
}
|
||||
va_start(ap, fmt) ;
|
||||
vsprintf(msg, fmt, ap) ;
|
||||
va_end(ap);
|
||||
|
||||
sprintf(all, "error: %s", msg);
|
||||
qfits_err_main_display(all);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,107 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file qerror.h
|
||||
@author N. Devillard
|
||||
@date Nov 2001
|
||||
@version $Revision: 1.4 $
|
||||
@brief qfits error handling
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: qerror.h,v 1.4 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.4 $
|
||||
*/
|
||||
|
||||
#ifndef _QERROR_H_
|
||||
#define _QERROR_H_
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* <dox> */
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name qfits_err_statget
|
||||
@memo Get the current status of error display.
|
||||
@return int 1 if error display is active, 0 if not.
|
||||
@doc
|
||||
|
||||
This function returns the current error display status. If it returns 1,
|
||||
it means that all calls to qfits_error/qfits_warning will display
|
||||
messages using the registered functions, otherwise they do nothing.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_err_statget(void);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name qfits_err_statset
|
||||
@memo Set the current status of error display.
|
||||
@param sta New status to be set.
|
||||
@return int giving the previous display status.
|
||||
@doc
|
||||
|
||||
This function sets the current error display status to the required
|
||||
value, and returns the previous value. It is useful to store the
|
||||
previous value, in view of restoring it afterwards, e.g. to make a
|
||||
function silent on all its errors. Example:
|
||||
|
||||
\begin{verbatim}
|
||||
int prev_stat = qfits_err_statset(0) ;
|
||||
function_call() ;
|
||||
qfits_err_statset(prev_stat);
|
||||
\end{verbatim}
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_err_statset(int sta);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@name qfits_err_register
|
||||
@memo Register a function to display error/warning messages.
|
||||
@param dispfn Display function (see doc below).
|
||||
@return int 0 if function was registered, -1 if not.
|
||||
@doc
|
||||
|
||||
This function registers a display function into the error-handling
|
||||
module. Display functions have the following prototype:
|
||||
|
||||
\begin{verbatim}
|
||||
void display_function(char * msg);
|
||||
\end{verbatim}
|
||||
|
||||
They are simple functions that expect a ready-made error message
|
||||
and return void. They can do whatever they want with the message
|
||||
(log it to a file, send it to a GUI, to the syslog, ...). The
|
||||
message is built using a printf-like statement in qfits_error and
|
||||
qfits_warning, then passed to all registered display functions.
|
||||
|
||||
A maximum of QFITS_ERR_MAXERRDISP can be registered (see source code).
|
||||
If the limit has been reached, this function will signal it by
|
||||
returning -1.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_err_register( void (*dispfn)(char*) ) ;
|
||||
|
||||
/* </dox> */
|
||||
|
||||
/* Public warning/error functions */
|
||||
void qfits_warning(char *fmt, ...);
|
||||
void qfits_error(char *fmt, ...);
|
||||
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,146 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file qfits_wrap.c
|
||||
@author N. Devillard
|
||||
@date Nov 2001
|
||||
@version $Revision: 1.10 $
|
||||
@brief
|
||||
|
||||
Interface file between python and the qfits library.
|
||||
All symbols are exported as the 'qfits' module under Python.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: qfits_wrap.c,v 1.10 2002/01/11 09:52:55 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/11 09:52:55 $
|
||||
$Revision: 1.10 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "Python.h"
|
||||
#include "qfits.h"
|
||||
|
||||
|
||||
static PyObject * _wrap_qfits_get_headers(PyObject * self, PyObject * args)
|
||||
{
|
||||
struct stat sta ;
|
||||
qfits_header * qh ;
|
||||
char * filename ;
|
||||
int xtnum ;
|
||||
int n_ext ;
|
||||
int i ;
|
||||
char key[FITS_LINESZ],
|
||||
val[FITS_LINESZ],
|
||||
com[FITS_LINESZ];
|
||||
char * pval ;
|
||||
|
||||
PyObject * hlist ;
|
||||
PyObject * hcur ;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &filename)) {
|
||||
return NULL ;
|
||||
}
|
||||
/* Check file's existence */
|
||||
if (stat(filename, &sta)!=0) {
|
||||
/* raise IOError exception */
|
||||
PyErr_SetString(PyExc_IOError, "cannot stat file");
|
||||
return NULL ;
|
||||
}
|
||||
/* Check file is FITS */
|
||||
if (is_fits_file(filename)!=1) {
|
||||
/* return None */
|
||||
return Py_BuildValue("") ;
|
||||
}
|
||||
/* Get number of extensions */
|
||||
n_ext = qfits_query_n_ext(filename);
|
||||
if (n_ext<0) {
|
||||
PyErr_SetString(PyExc_IOError, "cannot get number of FITS extensions");
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
hlist = PyList_New(1+n_ext) ;
|
||||
for (xtnum=0 ; xtnum<=n_ext ; xtnum++) {
|
||||
/* Query header */
|
||||
if (xtnum==0) {
|
||||
qh = qfits_header_read(filename);
|
||||
} else {
|
||||
qh = qfits_header_readext(filename, xtnum);
|
||||
}
|
||||
if (qh==NULL) {
|
||||
PyErr_SetString(PyExc_IOError, "cannot read header");
|
||||
return NULL ;
|
||||
}
|
||||
/* Build up a list of tuples (key,val,com) */
|
||||
hcur = PyList_New(qh->n) ;
|
||||
for (i=0 ; i<qh->n ; i++) {
|
||||
qfits_header_getitem(qh, i, key, val, com, NULL);
|
||||
pval = qfits_pretty_string(val);
|
||||
PyList_SetItem(hcur,i,Py_BuildValue("(sss)",key,pval,com)) ;
|
||||
}
|
||||
qfits_header_destroy(qh);
|
||||
/* Assign list into main list */
|
||||
PyList_SetItem(hlist, xtnum, hcur);
|
||||
}
|
||||
return hlist ;
|
||||
}
|
||||
|
||||
static PyObject * _wrap_qfits_expand_keyword(PyObject * self, PyObject * args)
|
||||
{
|
||||
char * key ;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &key)) {
|
||||
return NULL ;
|
||||
}
|
||||
return Py_BuildValue("s", qfits_expand_keyword(key));
|
||||
}
|
||||
|
||||
static PyObject * _wrap_qfits_datamd5(PyObject * self, PyObject * args)
|
||||
{
|
||||
char * filename ;
|
||||
char * md5hash ;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &filename)) {
|
||||
return NULL ;
|
||||
}
|
||||
md5hash = qfits_datamd5(filename);
|
||||
if (md5hash==NULL) {
|
||||
PyErr_SetString(PyExc_IOError, "cannot compute data MD5");
|
||||
return NULL ;
|
||||
}
|
||||
return Py_BuildValue("s", md5hash);
|
||||
}
|
||||
|
||||
static PyObject * _wrap_qfits_version(PyObject * self, PyObject * args)
|
||||
{
|
||||
return Py_BuildValue("s", qfits_version());
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef qfits_methods[] = {
|
||||
{"get_headers", _wrap_qfits_get_headers, METH_VARARGS},
|
||||
{"expand_keyword", _wrap_qfits_expand_keyword, METH_VARARGS},
|
||||
{"datamd5", _wrap_qfits_datamd5, METH_VARARGS},
|
||||
{"version", _wrap_qfits_version, METH_VARARGS},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
void initqfits(void)
|
||||
{
|
||||
PyObject * m ;
|
||||
m = Py_InitModule("qfits", qfits_methods);
|
||||
}
|
||||
|
||||
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,761 @@
|
|||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file simple.c
|
||||
@author N. Devillard
|
||||
@date Jan 1999
|
||||
@version $Revision: 1.4 $
|
||||
@brief Simple FITS access routines.
|
||||
|
||||
This module offers a number of very basic low-level FITS access
|
||||
routines.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: simple.c,v 1.4 2002/01/22 15:16:57 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/22 15:16:57 $
|
||||
$Revision: 1.4 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "simple.h"
|
||||
#include "fits_p.h"
|
||||
#include "expkey.h"
|
||||
#include "cache.h"
|
||||
#include "fits_std.h"
|
||||
#include "xmemory.h"
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Global variables
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The following global variables are only used for regular expression
|
||||
* matching of integers and floats. These definitions are private to
|
||||
* this module.
|
||||
*/
|
||||
/** A regular expression matching a floating-point number */
|
||||
static char regex_float[] =
|
||||
"^[+-]?([0-9]+[.]?[0-9]*|[.][0-9]+)([eE][+-]?[0-9]+)?$";
|
||||
|
||||
/** A regular expression matching an integer */
|
||||
static char regex_int[] = "^[+-]?[0-9]+$";
|
||||
|
||||
/** A regular expression matching a complex number (int or float) */
|
||||
static char regex_cmp[] =
|
||||
"^[+-]?([0-9]+[.]?[0-9]*|[.][0-9]+)([eE][+-]?[0-9]+)?[ ]+[+-]?([0-9]+[.]?[0-9]*|[.][0-9]+)([eE][+-]?[0-9]+)?$";
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Retrieve the value of a key in a FITS header
|
||||
@param filename Name of the FITS file to browse
|
||||
@param keyword Name of the keyword to find
|
||||
@return pointer to statically allocated character string
|
||||
|
||||
Provide the name of a FITS file and a keyword to look for. The input
|
||||
file is memory-mapped and the first keyword matching the requested one is
|
||||
located. The value corresponding to this keyword is copied to a
|
||||
statically allocated area, so do not modify it or free it.
|
||||
|
||||
The input keyword is first converted to upper case and expanded to
|
||||
the HIERARCH scheme if given in the shortFITS notation.
|
||||
|
||||
This function is pretty fast due to the mmapping. Due to buffering
|
||||
on most Unixes, it is possible to call many times this function in a
|
||||
row on the same file and do not suffer too much from performance
|
||||
problems. If the file contents are already in the cache, the file
|
||||
will not be re-opened every time.
|
||||
|
||||
It is possible, though, to modify this function to perform several
|
||||
searches in a row. See the source code.
|
||||
|
||||
Returns NULL in case the requested keyword cannot be found.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
char * qfits_query_hdr(char * filename, char * keyword)
|
||||
{
|
||||
char * where ;
|
||||
char * start ;
|
||||
char * value ;
|
||||
char test1, test2 ;
|
||||
int i ;
|
||||
int len ;
|
||||
int different ;
|
||||
struct stat fileinfo ;
|
||||
long int bufcount;
|
||||
char * exp_key ;
|
||||
|
||||
/* Bulletproof entries */
|
||||
if (filename==NULL || keyword==NULL) return NULL ;
|
||||
|
||||
/* Switch to uppercase and switch shortFITS notation to HIERARCH */
|
||||
exp_key = qfits_expand_keyword(keyword);
|
||||
|
||||
start = falloc(filename, 0, NULL) ;
|
||||
if (start==NULL) return NULL ;
|
||||
stat(filename, &fileinfo);
|
||||
bufcount=0;
|
||||
where = start ;
|
||||
len = (int)strlen(exp_key) ;
|
||||
while (1) {
|
||||
different=0 ;
|
||||
for (i=0 ; i<len ; i++) {
|
||||
if (where[i]!=exp_key[i]) {
|
||||
different++ ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if (!different) {
|
||||
/* Get the 2 characters after the keyword */
|
||||
test1 = where[len] ;
|
||||
test2 = where[len+1] ;
|
||||
/* If first subsequent character is the equal sign, bingo. */
|
||||
if (test1=='=') break ;
|
||||
/*
|
||||
* If first subsequent character is a blank and the one after is
|
||||
* equal or another blank, bingo.
|
||||
*/
|
||||
if (test1==' ' && (test2=='=' || test2==' ')) break ;
|
||||
}
|
||||
if ((where[0]=='E') &&
|
||||
(where[1]=='N') &&
|
||||
(where[2]=='D') &&
|
||||
(where[3]==' ')) {
|
||||
/* End of header detected */
|
||||
free(start);
|
||||
return NULL ;
|
||||
}
|
||||
/* Go to next line in header */
|
||||
where += 80 ;
|
||||
bufcount +=80;
|
||||
if (bufcount>=fileinfo.st_size){
|
||||
/* file damaged or not a fits file, avoid segmentation
|
||||
* fault */
|
||||
free(start);
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
}
|
||||
/* Found the keyword, now get its value */
|
||||
value = qfits_getvalue(where);
|
||||
free(start);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Retrieve the value of a keyin a FITS extension header.
|
||||
@param filename name of the FITS file to browse.
|
||||
@param keyword name of the FITS key to look for.
|
||||
@param xtnum xtension number
|
||||
@return pointer to statically allocated character string
|
||||
|
||||
Same as qfits_query_hdr but for extensions. xtnum starts from 1 to
|
||||
the number of extensions. If the required extension is 0, this
|
||||
function calls qfits_query_hdr().
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
char * qfits_query_ext(char * filename, char * keyword, int xtnum)
|
||||
{
|
||||
char * exp_key ;
|
||||
char * where ;
|
||||
char * start ;
|
||||
char * value ;
|
||||
char test1, test2 ;
|
||||
int seg_start ;
|
||||
int seg_size ;
|
||||
|
||||
if (xtnum==0) return qfits_query_hdr(filename, keyword);
|
||||
|
||||
/* Bulletproof entries */
|
||||
if (filename==NULL || keyword==NULL) return NULL ;
|
||||
|
||||
/* Expand keyword */
|
||||
exp_key = qfits_expand_keyword(keyword);
|
||||
|
||||
/*
|
||||
* Find out offsets to the required extension
|
||||
* Record the xtension start and stop offsets
|
||||
*/
|
||||
|
||||
if (qfits_get_hdrinfo(filename, xtnum, &seg_start, &seg_size)==-1) {
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory-map the input file and jump to start of xtension
|
||||
*/
|
||||
start = falloc(filename, seg_start, NULL);
|
||||
if (start==NULL) return NULL ;
|
||||
/*
|
||||
* Look for keyword in xtension
|
||||
*/
|
||||
while (1) {
|
||||
where = strstr(start, exp_key);
|
||||
if (where==NULL) {
|
||||
free(start);
|
||||
return NULL ;
|
||||
}
|
||||
if ((int)(where - start) > seg_size) {
|
||||
free(start);
|
||||
return NULL ;
|
||||
}
|
||||
test1 = where[(int)strlen(exp_key)] ;
|
||||
test2 = where[(int)strlen(exp_key)+1] ;
|
||||
|
||||
/* If first subsequent character is the equal sign, found it */
|
||||
if (test1=='=') break ;
|
||||
/*
|
||||
* If first subsequent character is a blank and the one after is
|
||||
* equal or another blank, found it
|
||||
*/
|
||||
if (test1==' ' && (test2=='=' || test2==' ')) break ;
|
||||
/* Not found */
|
||||
start = where+1 ;
|
||||
}
|
||||
/* Found the keyword, now get its value */
|
||||
value = qfits_getvalue(where);
|
||||
free(start);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Counts the number of extensions in a FITS file
|
||||
@param filename Name of the FITS file to browse.
|
||||
@return int
|
||||
|
||||
Counts how many extensions are in the file. Returns 0 if no
|
||||
extension is found, and -1 if an error occurred.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
int qfits_query_n_ext(char * filename)
|
||||
{
|
||||
return qfits_query(filename, QFITS_QUERY_N_EXT);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Clean out a FITS string value.
|
||||
@param s pointer to allocated FITS value string.
|
||||
@return pointer to statically allocated character string
|
||||
|
||||
From a string FITS value like 'marvin o''hara', remove head and tail
|
||||
quotes, replace double '' with simple ', trim blanks on each side,
|
||||
and return the result in a statically allocated area.
|
||||
|
||||
Examples:
|
||||
|
||||
- ['o''hara'] becomes [o'hara]
|
||||
- [' H '] becomes [H]
|
||||
- ['1.0 '] becomes [1.0]
|
||||
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
char * qfits_pretty_string(char * s)
|
||||
{
|
||||
static char pretty[81] ;
|
||||
int i,j ;
|
||||
|
||||
/* bulletproof */
|
||||
if (s==NULL) return NULL ;
|
||||
|
||||
pretty[0] = (char)0 ;
|
||||
if (s[0]!='\'') return s ;
|
||||
|
||||
/* skip first quote */
|
||||
i=1 ;
|
||||
j=0 ;
|
||||
/* trim left-side blanks */
|
||||
while (s[i]==' ') {
|
||||
if (i==(int)strlen(s)) break ;
|
||||
i++ ;
|
||||
}
|
||||
if (i>=(int)(strlen(s)-1)) return pretty ;
|
||||
/* copy string, changing double quotes to single ones */
|
||||
while (i<(int)strlen(s)) {
|
||||
if (s[i]=='\'') {
|
||||
i++ ;
|
||||
}
|
||||
pretty[j]=s[i];
|
||||
i++ ;
|
||||
j++ ;
|
||||
}
|
||||
/* NULL-terminate the pretty string */
|
||||
pretty[j+1]=(char)0;
|
||||
/* trim right-side blanks */
|
||||
j = (int)strlen(pretty)-1;
|
||||
while (pretty[j]==' ') j-- ;
|
||||
pretty[j+1]=(char)0;
|
||||
return pretty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a FITS value is boolean
|
||||
@param s FITS value as a string
|
||||
@return int 0 or 1
|
||||
|
||||
Identifies if a FITS value is boolean.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int qfits_is_boolean(char * s)
|
||||
{
|
||||
if (s==NULL) return 0 ;
|
||||
if (s[0]==0) return 0 ;
|
||||
if ((int)strlen(s)>1) return 0 ;
|
||||
if (s[0]=='T' || s[0]=='F') return 1 ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a FITS value is an int.
|
||||
@param s FITS value as a string
|
||||
@return int 0 or 1
|
||||
|
||||
Identifies if a FITS value is an integer.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int qfits_is_int(char * s)
|
||||
{
|
||||
static int first=1;
|
||||
static regex_t re_int;
|
||||
|
||||
if (s==NULL) return 0 ;
|
||||
if (s[0]==0) return 0 ;
|
||||
/* Compile the rule for integer pattern matching the first time */
|
||||
if (first) {
|
||||
first=0;
|
||||
if (regcomp(&re_int, ®ex_int[0], REG_EXTENDED|REG_NOSUB)!=0) {
|
||||
fprintf(stderr, "internal error: compiling int rule\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
return regexec(&re_int, s, 0, NULL, 0) ? 0 : 1 ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a FITS value is float.
|
||||
@param s FITS value as a string
|
||||
@return int 0 or 1
|
||||
|
||||
Identifies if a FITS value is float.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int qfits_is_float(char * s)
|
||||
{
|
||||
static int first=1;
|
||||
static regex_t re_float;
|
||||
if (s==NULL) return 0 ;
|
||||
if (s[0]==0) return 0 ;
|
||||
/* Compile the rule for float pattern matching the first time */
|
||||
if (first) {
|
||||
first=0;
|
||||
if (regcomp(&re_float, ®ex_float[0], REG_EXTENDED|REG_NOSUB)!=0) {
|
||||
fprintf(stderr, "internal error: compiling float rule\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
return regexec(&re_float, s, 0, NULL, 0) ? 0 : 1 ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a FITS value is complex.
|
||||
@param s FITS value as a string
|
||||
@return int 0 or 1
|
||||
|
||||
Identifies if a FITS value is complex.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
int qfits_is_complex(char * s)
|
||||
{
|
||||
static int first=1;
|
||||
static regex_t re_cmp;
|
||||
if (s==NULL) return 0 ;
|
||||
if (s[0]==0) return 0 ;
|
||||
/* Compile the rule for complex pattern matching the first time */
|
||||
if (first) {
|
||||
first=0;
|
||||
if (regcomp(&re_cmp, ®ex_cmp[0], REG_EXTENDED|REG_NOSUB)!=0) {
|
||||
fprintf(stderr, "internal error: compiling complex rule\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
return regexec(&re_cmp, s, 0, NULL, 0) ? 0 : 1 ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a FITS value is string.
|
||||
@param s FITS value as a string
|
||||
@return int 0 or 1
|
||||
|
||||
Identifies if a FITS value is a string.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int qfits_is_string(char * s)
|
||||
{
|
||||
if (s==NULL) return 0 ;
|
||||
if (s[0]=='\'') return 1 ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify the type of a FITS value given as a string.
|
||||
@param s FITS value as a string
|
||||
@return integer naming the FITS type
|
||||
|
||||
Returns the following value:
|
||||
|
||||
- QFITS_UNKNOWN (0) for an unknown type.
|
||||
- QFITS_BOOLEAN (1) for a boolean type.
|
||||
- QFITS_INT (2) for an integer type.
|
||||
- QFITS_FLOAT (3) for a floating-point type.
|
||||
- QFITS_COMPLEX (4) for a complex number.
|
||||
- QFITS_STRING (5) for a FITS string.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int qfits_get_type(char * s)
|
||||
{
|
||||
if (qfits_is_boolean(s)) return QFITS_BOOLEAN ;
|
||||
if (qfits_is_int(s)) return QFITS_INT ;
|
||||
if (qfits_is_float(s)) return QFITS_FLOAT ;
|
||||
if (qfits_is_complex(s)) return QFITS_COMPLEX ;
|
||||
if (qfits_is_string(s)) return QFITS_STRING ;
|
||||
return QFITS_UNKNOWN ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Retrieve offset to start and size of a header in a FITS file.
|
||||
@param filename Name of the file to examine
|
||||
@param xtnum Extension number (0 for main)
|
||||
@param seg_start Segment start in bytes (output)
|
||||
@param seg_size Segment size in bytes (output)
|
||||
@return int 0 if Ok, -1 otherwise.
|
||||
|
||||
This function retrieves the two most important informations about
|
||||
a header in a FITS file: the offset to its beginning, and the size
|
||||
of the header in bytes. Both values are returned in the passed
|
||||
pointers to ints. It is Ok to pass NULL for any pointer if you do
|
||||
not want to retrieve the associated value.
|
||||
|
||||
You must provide an extension number for the header, 0 meaning the
|
||||
main header in the file.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_get_hdrinfo(
|
||||
char * filename,
|
||||
int xtnum,
|
||||
int * seg_start,
|
||||
int * seg_size
|
||||
)
|
||||
{
|
||||
if (filename==NULL || xtnum<0 || (seg_start==NULL && seg_size==NULL)) {
|
||||
return -1 ;
|
||||
}
|
||||
if (seg_start!=NULL) {
|
||||
*seg_start = qfits_query(filename, QFITS_QUERY_HDR_START | xtnum);
|
||||
if (*seg_start<0)
|
||||
return -1 ;
|
||||
}
|
||||
if (seg_size!=NULL) {
|
||||
*seg_size = qfits_query(filename, QFITS_QUERY_HDR_SIZE | xtnum);
|
||||
if (*seg_size<0)
|
||||
return -1 ;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Retrieve offset to start and size of a data section in a file.
|
||||
@param filename Name of the file to examine.
|
||||
@param xtnum Extension number (0 for main).
|
||||
@param seg_start Segment start in bytes (output).
|
||||
@param seg_size Segment size in bytes (output).
|
||||
@return int 0 if Ok, -1 otherwise.
|
||||
|
||||
This function retrieves the two most important informations about
|
||||
a data section in a FITS file: the offset to its beginning, and the size
|
||||
of the section in bytes. Both values are returned in the passed
|
||||
pointers to ints. It is Ok to pass NULL for any pointer if you do
|
||||
not want to retrieve the associated value.
|
||||
|
||||
You must provide an extension number for the header, 0 meaning the
|
||||
main header in the file.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_get_datinfo(
|
||||
char * filename,
|
||||
int xtnum,
|
||||
int * seg_start,
|
||||
int * seg_size
|
||||
)
|
||||
{
|
||||
if (filename==NULL || xtnum<0 || (seg_start==NULL && seg_size==NULL)) {
|
||||
return -1 ;
|
||||
}
|
||||
if (seg_start!=NULL) {
|
||||
*seg_start = qfits_query(filename, QFITS_QUERY_DAT_START | xtnum);
|
||||
if (*seg_start<0)
|
||||
return -1 ;
|
||||
}
|
||||
if (seg_size!=NULL) {
|
||||
*seg_size = qfits_query(filename, QFITS_QUERY_DAT_SIZE | xtnum);
|
||||
if (*seg_size<0)
|
||||
return -1 ;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Retrieve the card containing a keyword in the main header.
|
||||
@param filename Name of the FITS file to examine.
|
||||
@param keyword Keyword to look for in header.
|
||||
@return Pointer to statically allocated character string
|
||||
|
||||
Retrieve the whole FITS line associated to a given keyword in the
|
||||
main header. The returned string is statically allocated, so do not
|
||||
modify it or try to free it. Returns NULL if an error occurred or
|
||||
the keyword cannot be found.
|
||||
|
||||
The input keyword is first converted to upper case and expanded to
|
||||
the HIERARCH scheme if given in the shortFITS notation.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
char *
|
||||
qfits_query_card_in_header(char * filename, char * keyword)
|
||||
{
|
||||
char * exp_key ;
|
||||
char * where ;
|
||||
char * start ;
|
||||
static char value[81] ;
|
||||
|
||||
/* Bulletproof entries */
|
||||
if (filename==NULL || keyword==NULL) return NULL ;
|
||||
|
||||
exp_key = qfits_expand_keyword(keyword);
|
||||
start = falloc(filename, 0, NULL) ;
|
||||
if (start==NULL) return NULL ;
|
||||
while (1) {
|
||||
where = strstr(start, exp_key);
|
||||
if (where==NULL) {
|
||||
free(start);
|
||||
return NULL ;
|
||||
}
|
||||
if (((where-start)%80) == 0) /* found */ break ;
|
||||
/* Not found */
|
||||
start = where+1 ;
|
||||
}
|
||||
/* Found the keyword, now get the corresponding FITS card */
|
||||
memcpy(value, where, 80);
|
||||
free(start);
|
||||
value[80] = (char)0 ;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Replace a card in a FITS (main) header by a given card
|
||||
@param filename Name of the FITS file to modify.
|
||||
@param keyword Where to substitute a card in the header.
|
||||
@param substitute What to replace the line with.
|
||||
@return int 0 if Ok, -1 otherwise
|
||||
|
||||
Replaces a whole card (80 chars) in a FITS header by a given FITS
|
||||
line (80 chars). The replacing line is assumed correctly formatted
|
||||
and containing at least 80 characters. The file is modified: it must
|
||||
be accessible in read/write mode.
|
||||
|
||||
The input keyword is first converted to upper case and expanded to
|
||||
the HIERARCH scheme if given in the shortFITS notation.
|
||||
|
||||
Returns 0 if everything worked Ok, -1 otherwise.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int qfits_replace_card(
|
||||
char * filename,
|
||||
char * keyword,
|
||||
char * substitute
|
||||
)
|
||||
{
|
||||
char * exp_key ;
|
||||
int fd ;
|
||||
char * buf ;
|
||||
char * buf2 ;
|
||||
char * where ;
|
||||
int hs ;
|
||||
|
||||
|
||||
/* Bulletproof entries */
|
||||
if (filename==NULL || keyword==NULL || substitute==NULL) return -1 ;
|
||||
|
||||
/* Expand keyword */
|
||||
exp_key = qfits_expand_keyword(keyword);
|
||||
/*
|
||||
* Memory-map the FITS header of the input file
|
||||
*/
|
||||
|
||||
qfits_get_hdrinfo(filename, 0, NULL, &hs) ;
|
||||
if (hs < 1) {
|
||||
fprintf(stderr, "error getting FITS header size for %s\n", filename);
|
||||
return -1 ;
|
||||
}
|
||||
fd = open(filename, O_RDWR) ;
|
||||
if (fd == -1) {
|
||||
return -1 ;
|
||||
}
|
||||
buf = (char*)mmap(0,
|
||||
hs,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
fd,
|
||||
0) ;
|
||||
if (buf == (char*)-1) {
|
||||
perror("mmap") ;
|
||||
close(fd) ;
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply search and replace for the input keyword lists
|
||||
*/
|
||||
|
||||
buf2 = malloc(hs+1) ;
|
||||
memcpy(buf2, buf, hs) ;
|
||||
buf2[hs] = (char)0 ;
|
||||
where = buf2 ;
|
||||
do {
|
||||
where = strstr(where, exp_key);
|
||||
if (where == NULL) {
|
||||
close(fd);
|
||||
munmap(buf,hs);
|
||||
free(buf2) ;
|
||||
return -1 ;
|
||||
}
|
||||
if ((where-buf2)%80) where++ ;
|
||||
} while ((where-buf2)%80) ;
|
||||
|
||||
where = buf + (int)(where - buf2) ;
|
||||
|
||||
/* Replace current placeholder by blanks */
|
||||
memset(where, ' ', 80);
|
||||
/* Copy substitute into placeholder */
|
||||
memcpy(where, substitute, strlen(substitute));
|
||||
|
||||
close(fd) ;
|
||||
munmap(buf, hs) ;
|
||||
free(buf2) ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Replace a placeholder in a FITS header by a given card.
|
||||
@param filename Name of the FITS file to modify.
|
||||
@param placeholder Name of the placeholder to replace.
|
||||
@param substitute What to replace the line with.
|
||||
@return int 0 if Ok, -1 otherwise
|
||||
|
||||
Similar to qfits_replace_card, but to replace placeholder in FITS
|
||||
(main) headers. A placeholder is defined as being something like:
|
||||
|
||||
COMMENT %s
|
||||
|
||||
In the search process to look for placeholders, %s is replaced with
|
||||
the given character string. The default placeholder to look for is
|
||||
simply 'PLACEHOLDER'.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
int qfits_replace_placeholder(
|
||||
char * filename,
|
||||
char * placeholder,
|
||||
char * substitute
|
||||
)
|
||||
{
|
||||
char to_find[FITS_LINESZ] ;
|
||||
|
||||
if (filename==NULL ||
|
||||
placeholder==NULL ||
|
||||
substitute==NULL) {
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
/* Format string to search for */
|
||||
sprintf(to_find, "COMMENT %s", placeholder) ;
|
||||
|
||||
/* Replace card */
|
||||
return qfits_replace_card(filename, to_find, substitute) ;
|
||||
}
|
||||
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,339 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file simple.h
|
||||
@author N. Devillard
|
||||
@date Jan 1999
|
||||
@version $Revision: 1.5 $
|
||||
@brief Simple FITS access routines.
|
||||
|
||||
This module offers a number of very basic low-level FITS access
|
||||
routines.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: simple.h,v 1.5 2002/01/22 15:16:57 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/22 15:16:57 $
|
||||
$Revision: 1.5 $
|
||||
*/
|
||||
|
||||
#ifndef _SIMPLE_H_
|
||||
#define _SIMPLE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* <dox> */
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** Unknown type for FITS value */
|
||||
#define QFITS_UNKNOWN 0
|
||||
/** Boolean type for FITS value */
|
||||
#define QFITS_BOOLEAN 1
|
||||
/** Int type for FITS value */
|
||||
#define QFITS_INT 2
|
||||
/** Float type for FITS value */
|
||||
#define QFITS_FLOAT 3
|
||||
/** Complex type for FITS value */
|
||||
#define QFITS_COMPLEX 4
|
||||
/** String type for FITS value */
|
||||
#define QFITS_STRING 5
|
||||
|
||||
/** Default name of a place holder, as a character string */
|
||||
#define QFITS_PLACEHOLDER "PLACEHOLDER"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Retrieve the value of a key in a FITS header
|
||||
@param filename Name of the FITS file to browse
|
||||
@param keyword Name of the keyword to find
|
||||
@return pointer to statically allocated character string
|
||||
|
||||
Provide the name of a FITS file and a keyword to look for. The input
|
||||
file is mmap'ed and the first keyword matching the requested one is
|
||||
located. The value corresponding to this keyword is copied to a
|
||||
statically allocated area, so do not modify it or free it.
|
||||
|
||||
The input keyword is first converted to upper case and expanded to
|
||||
the HIERARCH scheme if given in the shortFITS notation.
|
||||
|
||||
This function is pretty fast due to the mmapping. Due to buffering
|
||||
on most Unixes, it is possible to call many times this function in a
|
||||
row on the same file and do not suffer too much from performance
|
||||
problems. If the file contents are already in the cache, the file
|
||||
will not be re-opened every time.
|
||||
|
||||
It is possible, though, to modify this function to perform several
|
||||
searches in a row. See the source code.
|
||||
|
||||
Returns NULL in case the requested keyword cannot be found.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_query_hdr(char * filename, char * keyword) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Retrieve the value of a keyin a FITS extension header.
|
||||
@param filename name of the FITS file to browse.
|
||||
@param keyword name of the FITS key to look for.
|
||||
@param xtnum xtension number
|
||||
@return pointer to statically allocated character string
|
||||
|
||||
Same as qfits_query_hdr but for extensions. xtnum starts from 1 to
|
||||
the number of extensions. If the required extension is 0, this
|
||||
function calls qfits_query_hdr().
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_query_ext(char * filename, char * keyword, int xtnum);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Counts the number of extensions in a FITS file
|
||||
@param filename Name of the FITS file to browse.
|
||||
@return int
|
||||
|
||||
Counts how many extensions are in the file. Returns 0 if no
|
||||
extension is found, and -1 if an error occurred.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_query_n_ext(char * filename);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Clean out a FITS string value.
|
||||
@param s pointer to allocated FITS value string.
|
||||
@return pointer to statically allocated character string
|
||||
|
||||
From a string FITS value like 'marvin o''hara', remove head and tail
|
||||
quotes, replace double '' with simple ', trim blanks on each side,
|
||||
and return the result in a statically allocated area.
|
||||
|
||||
Examples:
|
||||
|
||||
- ['o''hara'] becomes [o'hara]
|
||||
- [' H '] becomes [H]
|
||||
- ['1.0 '] becomes [1.0]
|
||||
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_pretty_string(char * s);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a FITS value is boolean
|
||||
@param s FITS value as a string
|
||||
@return int 0 or 1
|
||||
|
||||
Identifies if a FITS value is boolean.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_is_boolean(char * s);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a FITS value is an int.
|
||||
@param s FITS value as a string
|
||||
@return int 0 or 1
|
||||
|
||||
Identifies if a FITS value is an integer.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_is_int(char * s);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a FITS value is float.
|
||||
@param s FITS value as a string
|
||||
@return int 0 or 1
|
||||
|
||||
Identifies if a FITS value is float.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_is_float(char * s);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a FITS value is complex.
|
||||
@param s FITS value as a string
|
||||
@return int 0 or 1
|
||||
|
||||
Identifies if a FITS value is complex.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_is_complex(char * s);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify if a FITS value is string.
|
||||
@param s FITS value as a string
|
||||
@return int 0 or 1
|
||||
|
||||
Identifies if a FITS value is a string.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_is_string(char * s);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify the type of a FITS value given as a string.
|
||||
@param s FITS value as a string
|
||||
@return integer naming the FITS type
|
||||
|
||||
Returns the following value:
|
||||
|
||||
- QFITS_UNKNOWN (0) for an unknown type.
|
||||
- QFITS_BOOLEAN (1) for a boolean type.
|
||||
- QFITS_INT (2) for an integer type.
|
||||
- QFITS_FLOAT (3) for a floating-point type.
|
||||
- QFITS_COMPLEX (4) for a complex number.
|
||||
- QFITS_STRING (5) for a FITS string.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_get_type(char * s);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Retrieve offset to start and size of a header in a FITS file.
|
||||
@param filename Name of the file to examine
|
||||
@param xtnum Extension number (0 for main)
|
||||
@param seg_start Segment start in bytes (output)
|
||||
@param seg_size Segment size in bytes (output)
|
||||
@return int 0 if Ok, -1 otherwise.
|
||||
|
||||
This function retrieves the two most important informations about
|
||||
a header in a FITS file: the offset to its beginning, and the size
|
||||
of the header in bytes. Both values are returned in the passed
|
||||
pointers to ints. It is Ok to pass NULL for any pointer if you do
|
||||
not want to retrieve the associated value.
|
||||
|
||||
You must provide an extension number for the header, 0 meaning the
|
||||
main header in the file.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_get_hdrinfo(
|
||||
char * filename,
|
||||
int xtnum,
|
||||
int * seg_start,
|
||||
int * seg_size
|
||||
);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Retrieve offset to start and size of a data section in a file.
|
||||
@param filename Name of the file to examine.
|
||||
@param xtnum Extension number (0 for main).
|
||||
@param seg_start Segment start in bytes (output).
|
||||
@param seg_size Segment size in bytes (output).
|
||||
@return int 0 if Ok, -1 otherwise.
|
||||
|
||||
This function retrieves the two most important informations about
|
||||
a data section in a FITS file: the offset to its beginning, and the size
|
||||
of the section in bytes. Both values are returned in the passed
|
||||
pointers to ints. It is Ok to pass NULL for any pointer if you do
|
||||
not want to retrieve the associated value.
|
||||
|
||||
You must provide an extension number for the header, 0 meaning the
|
||||
main header in the file.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_get_datinfo(
|
||||
char * filename,
|
||||
int xtnum,
|
||||
int * seg_start,
|
||||
int * seg_size
|
||||
);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Retrieve the card containing a keyword in the main header.
|
||||
@param filename Name of the FITS file to examine.
|
||||
@param keyword Keyword to look for in header.
|
||||
@return Pointer to statically allocated character string
|
||||
|
||||
Retrieve the whole FITS line associated to a given keyword in the
|
||||
main header. The returned string is statically allocated, so do not
|
||||
modify it or try to free it. Returns NULL if an error occurred or
|
||||
the keyword cannot be found.
|
||||
|
||||
The input keyword is first converted to upper case and expanded to
|
||||
the HIERARCH scheme if given in the shortFITS notation.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_query_card_in_header(char * filename, char * keyword);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Replace a card in a FITS (main) header by a given card
|
||||
@param filename Name of the FITS file to modify.
|
||||
@param keyword Where to substitute a card in the header.
|
||||
@param substitute What to replace the line with.
|
||||
@return int 0 if Ok, -1 otherwise
|
||||
|
||||
Replaces a whole card (80 chars) in a FITS header by a given FITS
|
||||
line (80 chars). The replacing line is assumed correctly formatted
|
||||
and containing at least 80 characters. The file is modified: it must
|
||||
be accessible in read/write mode.
|
||||
|
||||
The input keyword is first converted to upper case and expanded to
|
||||
the HIERARCH scheme if given in the shortFITS notation.
|
||||
|
||||
Returns 0 if everything worked Ok, -1 otherwise.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_replace_card(char * filename, char * keyword, char * substitute) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Replace a placeholder in a FITS header by a given card.
|
||||
@param filename Name of the FITS file to modify.
|
||||
@param placeholder Name of the placeholder to replace.
|
||||
@param substitute What to replace the line with.
|
||||
@return int 0 if Ok, -1 otherwise
|
||||
|
||||
Similar to fits_replace_card, but to replace placeholder in FITS
|
||||
(main) headers. A placeholder is defined as being something like:
|
||||
|
||||
COMMENT %s
|
||||
|
||||
In the search process to look for placeholders, %s is replaced with
|
||||
the given character string. The default placeholder to look for is
|
||||
simply 'PLACEHOLDER'.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_replace_placeholder(
|
||||
char * filename,
|
||||
char * placeholder,
|
||||
char * substitute
|
||||
);
|
||||
|
||||
|
||||
/* </dox> */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file static_sz.h
|
||||
@author N. Devillard
|
||||
@date Dec 1999
|
||||
@version $Revision: 1.3 $
|
||||
@brief Definitions for various fixed sizes.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: static_sz.h,v 1.3 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.3 $
|
||||
*/
|
||||
|
||||
#ifndef _STATIC_SZ_H_
|
||||
#define _STATIC_SZ_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* <dox> */
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** Maximum supported file name size */
|
||||
#define FILENAMESZ 512
|
||||
|
||||
/** Maximum number of characters per line in an ASCII file */
|
||||
#define ASCIILINESZ 1024
|
||||
|
||||
/* </dox> */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,282 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file t_iso8601.c
|
||||
@author N. Devillard
|
||||
@date Aug 1999
|
||||
@version $Revision: 1.2 $
|
||||
@brief Get date/time, possibly in ISO8601 format.
|
||||
|
||||
This module contains various utilities to get the current date/time,
|
||||
and possibly format it according to the ISO 8601 format.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: t_iso8601.c,v 1.2 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.2 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "t_iso8601.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Macros
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** Get century from a date in long format */
|
||||
#define GET_CENTURY(d) (int) ( (d) / 1000000L)
|
||||
/** Get century year from a date in long format */
|
||||
#define GET_CCYEAR(d) (int) ( (d) / 10000L)
|
||||
/** Get year from a date in long format */
|
||||
#define GET_YEAR(d) (int) (((d) % 1000000L) / 10000L)
|
||||
/** Get month from a date in long format */
|
||||
#define GET_MONTH(d) (int) (((d) % 10000L) / 100)
|
||||
/** Get day from a date in long format */
|
||||
#define GET_DAY(d) (int) ( (d) % 100)
|
||||
|
||||
/** Get hours from a date in long format */
|
||||
#define GET_HOUR(t) (int) ( (t) / 1000000L)
|
||||
/** Get minutes from a date in long format */
|
||||
#define GET_MINUTE(t) (int) (((t) % 1000000L) / 10000L)
|
||||
/** Get seconds from a date in long format */
|
||||
#define GET_SECOND(t) (int) (((t) % 10000L) / 100)
|
||||
/** Get centi-seconds from a date in long format */
|
||||
#define GET_CENTI(t) (int) ( (t) % 100)
|
||||
|
||||
/** Make date in long format from its components */
|
||||
#define MAKE_DATE(c,y,m,d) (long) (c) * 1000000L + \
|
||||
(long) (y) * 10000L + \
|
||||
(long) (m) * 100 + (d)
|
||||
/** Make time in long format from its components */
|
||||
#define MAKE_TIME(h,m,s,c) (long) (h) * 1000000L + \
|
||||
(long) (m) * 10000L + \
|
||||
(long) (s) * 100 + (c)
|
||||
|
||||
|
||||
/** Interval values, specified in centiseconds */
|
||||
|
||||
#define INTERVAL_CENTI 1
|
||||
#define INTERVAL_SEC 100
|
||||
#define INTERVAL_MIN 6000
|
||||
#define INTERVAL_HOUR 360000L
|
||||
#define INTERVAL_DAY 8640000L
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Private to this module
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static long timer_to_date(time_t time_secs);
|
||||
static long timer_to_time(time_t time_secs);
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function ANSI C prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Returns the current date as a long (CCYYMMDD).
|
||||
@return The current date as a long number.
|
||||
|
||||
Returns the current date as a long value (CCYYMMDD). Since most
|
||||
system clocks do not return a century, this function assumes that
|
||||
all years 80 and above are in the 20th century, and all years 00 to
|
||||
79 are in the 21st century. For best results, consume before 1 Jan
|
||||
2080.
|
||||
|
||||
Example: 19 Oct 2000 is returned as 20001019
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
long date_now (void)
|
||||
{
|
||||
return (timer_to_date (time (NULL)));
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Returns the current time as a long (HHMMSSCC).
|
||||
@return The current time as a long number.
|
||||
|
||||
Returns the current time as a long value (HHMMSSCC). If the system
|
||||
clock does not return centiseconds, these are set to zero.
|
||||
|
||||
Example: 15:36:12.84 is returned as 15361284
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
long time_now(void)
|
||||
{
|
||||
struct timeval time_struct;
|
||||
|
||||
gettimeofday (&time_struct, 0);
|
||||
return (timer_to_time (time_struct.tv_sec)
|
||||
+ time_struct.tv_usec / 10000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Converts a timer value to a date.
|
||||
@param time_secs Current time definition in seconds.
|
||||
@return Current date as a long (CCYYMMDD).
|
||||
|
||||
Converts the supplied timer value into a long date value. Dates are
|
||||
stored as long values: CCYYMMDD. If the supplied value is zero,
|
||||
returns zero. If the supplied value is out of range, returns 1
|
||||
January, 1970 (19700101). The timer value is assumed to be UTC
|
||||
(GMT).
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static long timer_to_date(time_t time_secs)
|
||||
{
|
||||
struct tm *time_struct;
|
||||
|
||||
if (time_secs == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
/* Convert into a long value CCYYMMDD */
|
||||
time_struct = localtime (&time_secs);
|
||||
if (time_struct) {
|
||||
time_struct-> tm_year += 1900;
|
||||
return (MAKE_DATE ( time_struct-> tm_year / 100,
|
||||
time_struct-> tm_year % 100,
|
||||
time_struct-> tm_mon + 1,
|
||||
time_struct-> tm_mday));
|
||||
} else {
|
||||
return (19700101);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Convert a timer value to a time.
|
||||
@param time_secs Current time definition in seconds.
|
||||
@return Current time as a long.
|
||||
|
||||
Converts the supplied timer value into a long time value. Times are
|
||||
stored as long values: HHMMSS00. Since the timer value does not
|
||||
hold centiseconds, these are set to zero. If the supplied value was
|
||||
zero or invalid, returns zero. The timer value is assumed to be UTC
|
||||
(GMT).
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
static long timer_to_time(time_t time_secs)
|
||||
{
|
||||
struct tm *time_struct;
|
||||
|
||||
if (time_secs == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
/* Convert into a long value HHMMSS00 */
|
||||
time_struct = localtime (&time_secs);
|
||||
if (time_struct) {
|
||||
return (MAKE_TIME (time_struct-> tm_hour,
|
||||
time_struct-> tm_min,
|
||||
time_struct-> tm_sec,
|
||||
0));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function codes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Returns the current date as a static string.
|
||||
@return Pointer to statically allocated string.
|
||||
|
||||
Build and return a string containing the date of today in ISO8601
|
||||
format. The returned pointer points to a statically allocated string
|
||||
in the function, so no need to free it.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
char * get_date_iso8601(void)
|
||||
{
|
||||
static char date_iso8601[20] ;
|
||||
long curdate ;
|
||||
|
||||
curdate = date_now() ;
|
||||
sprintf(date_iso8601, "%04d-%02d-%02d",
|
||||
GET_CCYEAR(curdate),
|
||||
GET_MONTH(curdate),
|
||||
GET_DAY(curdate));
|
||||
return date_iso8601 ;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Returns the current date and time as a static string.
|
||||
@return Pointer to statically allocated string
|
||||
|
||||
Build and return a string containing the date of today and the
|
||||
current time in ISO8601 format. The returned pointer points to a
|
||||
statically allocated string in the function, so no need to free it.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
char * get_datetime_iso8601(void)
|
||||
{
|
||||
static char date_iso8601[20] ;
|
||||
long curdate ;
|
||||
long curtime ;
|
||||
|
||||
curdate = date_now() ;
|
||||
curtime = time_now() ;
|
||||
|
||||
sprintf(date_iso8601, "%04d-%02d-%02dT%02d:%02d:%02d",
|
||||
GET_CCYEAR(curdate),
|
||||
GET_MONTH(curdate),
|
||||
GET_DAY(curdate),
|
||||
GET_HOUR(curtime),
|
||||
GET_MINUTE(curtime),
|
||||
GET_SECOND(curtime));
|
||||
return date_iso8601 ;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf( "date now %ld\n"
|
||||
"time now %ld\n"
|
||||
"date iso8601 %s\n"
|
||||
"date/time iso 8601 %s\n",
|
||||
date_now(),
|
||||
time_now(),
|
||||
get_date_iso8601(),
|
||||
get_datetime_iso8601());
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,96 @@
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file t_iso8601.h
|
||||
@author N. Devillard
|
||||
@date Aug 1999
|
||||
@version $Revision: 1.3 $
|
||||
@brief Get date/time, possibly in ISO8601 format.
|
||||
|
||||
This module contains various utilities to get the current date/time,
|
||||
and possibly format it according to the ISO 8601 format.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
|
||||
$Id: t_iso8601.h,v 1.3 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.3 $
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _T_ISO8601_H_
|
||||
#define _T_ISO8601_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* <dox> */
|
||||
/*---------------------------------------------------------------------------
|
||||
Function ANSI C prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Returns the current date as a long (CCYYMMDD).
|
||||
@return The current date as a long number.
|
||||
|
||||
Returns the current date as a long value (CCYYMMDD). Since most
|
||||
system clocks do not return a century, this function assumes that
|
||||
all years 80 and above are in the 20th century, and all years 00 to
|
||||
79 are in the 21st century. For best results, consume before 1 Jan
|
||||
2080.
|
||||
|
||||
Example: 19 Oct 2000 is returned as 20001019
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
long date_now (void);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Returns the current time as a long (HHMMSSCC).
|
||||
@return The current time as a long number.
|
||||
|
||||
Returns the current time as a long value (HHMMSSCC). If the system
|
||||
clock does not return centiseconds, these are set to zero.
|
||||
|
||||
Example: 15:36:12.84 is returned as 15361284
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
long time_now(void);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Returns the current date as a static string.
|
||||
@return Pointer to statically allocated string.
|
||||
|
||||
Build and return a string containing the date of today in ISO8601
|
||||
format. The returned pointer points to a statically allocated string
|
||||
in the function, so no need to free it.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * get_date_iso8601(void);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Returns the current date and time as a static string.
|
||||
@return Pointer to statically allocated string
|
||||
|
||||
Build and return a string containing the date of today and the
|
||||
current time in ISO8601 format. The returned pointer points to a
|
||||
statically allocated string in the function, so no need to free it.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
char * get_datetime_iso8601(void);
|
||||
|
||||
/* </dox> */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,407 @@
|
|||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@file tfits.h
|
||||
@author Yves Jung
|
||||
@date July 1999
|
||||
@version $Revision: 1.5 $
|
||||
@brief FITS table handling
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: tfits.h,v 1.5 2002/01/10 08:53:08 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/10 08:53:08 $
|
||||
$Revision: 1.5 $
|
||||
*/
|
||||
|
||||
#ifndef _TFITS_H_
|
||||
#define _TFITS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fits_h.h"
|
||||
#include "static_sz.h"
|
||||
|
||||
/* <dox> */
|
||||
/*---------------------------------------------------------------------------
|
||||
Defines
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* The following defines the maximum acceptable size for a FITS value */
|
||||
#define FITSVALSZ 60
|
||||
|
||||
#define QFITS_INVALIDTABLE 0
|
||||
#define QFITS_BINTABLE 1
|
||||
#define QFITS_ASCIITABLE 2
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
New types
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Column object
|
||||
|
||||
This structure contains all information needed to read a column in a table.
|
||||
These informations come from the header.
|
||||
The qfits_table object contains a list of qfits_col objects.
|
||||
|
||||
This structure has to be created from scratch and filled if one want to
|
||||
generate a FITS table.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
typedef struct _qfits_col_
|
||||
{
|
||||
/**
|
||||
Number of rows in the column. In a same table, all columns have
|
||||
the same nelem value.
|
||||
*/
|
||||
int nelem ;
|
||||
|
||||
/**
|
||||
Number of elements in one field. There are some differences according
|
||||
types
|
||||
- If the field contains a string, natoms = 1. In this case, the number
|
||||
of characters is given by ascii_size.
|
||||
- If the field contains elements of types 'L', 'I', 'J', 'E', 'D' or
|
||||
'B', natoms is simply the number of elements.
|
||||
- For complex types ('C' or 'M') natoms is the number of double or
|
||||
float (number of complex * 2).
|
||||
- If the field contains elements of type P (pair of int), natoms is
|
||||
the number of int (nb of 'P' element * 2)
|
||||
*/
|
||||
int natoms ;
|
||||
|
||||
/**
|
||||
Size of one element in bytes. In ASCII tables, atom_size is the size
|
||||
of the element once it has been converted in its 'destination' type.
|
||||
For example, if "123" is contained in an ASCII table in a column
|
||||
defined as I type, natoms=1, ascii_size=3, atom_size=4.
|
||||
In ASCII tables:
|
||||
- type 'A' : atom_size = ascii_size = number of chars
|
||||
- type 'I', 'F' or 'E' : atom_size = 4
|
||||
- type 'D' : atom_size = 8
|
||||
In BIN tables :
|
||||
- type 'A' : atom_size = ascii_size = atom_nb = number of chars
|
||||
- type 'L', 'X', B' : atom_size = 1
|
||||
- type 'I' : atom_size = 2
|
||||
- type 'E', 'J', 'C', 'P' : atom_size = 4
|
||||
- type 'D', 'M' : atom_size = 8
|
||||
*/
|
||||
int atom_size ;
|
||||
|
||||
/**
|
||||
Only for ASCII fields (0 otherwise). Nb of characters of the field.
|
||||
*/
|
||||
int ascii_size ;
|
||||
|
||||
/**
|
||||
Type of data in the column as specified in TFORM keyword
|
||||
In ASCII tables : A, I, F, E or D
|
||||
In BIN tables : L, X, B, I, J, A, E, D, C, M or P
|
||||
*/
|
||||
char atom_type ;
|
||||
|
||||
/**
|
||||
Number of atoms per field as specified in TFORM keyword
|
||||
Differ from natoms for ASCII table fields of type different from A:
|
||||
you can have the string "1234" (natoms = 1) specified as I4
|
||||
(atom_nb = 4)
|
||||
*/
|
||||
int atom_nb ;
|
||||
|
||||
/**
|
||||
Label of the column
|
||||
*/
|
||||
char tlabel[FITSVALSZ] ;
|
||||
|
||||
/**
|
||||
Unit of the data
|
||||
*/
|
||||
char tunit[FITSVALSZ] ;
|
||||
|
||||
/**
|
||||
Null value
|
||||
*/
|
||||
char nullval[FITSVALSZ] ;
|
||||
|
||||
/**
|
||||
Display format
|
||||
*/
|
||||
char disp[FITSVALSZ] ;
|
||||
|
||||
/**
|
||||
zero and scale are used when the quantity in the field does not
|
||||
represent a true physical quantity. Basically, thez should be used
|
||||
when they are present: physical_value = zero + scale * field_value
|
||||
They are read from TZERO and TSCAL in the header
|
||||
*/
|
||||
int zero_present ;
|
||||
float zero ;
|
||||
int scale_present ;
|
||||
float scale ;
|
||||
|
||||
/**
|
||||
Offset between the beg. of the table and the beg. of the column.
|
||||
*/
|
||||
int off_beg ;
|
||||
|
||||
/**
|
||||
Width of the table in bytes
|
||||
*/
|
||||
int off_jmp ;
|
||||
|
||||
/**
|
||||
Flag to know if the column is readable. An empty col is not readable
|
||||
*/
|
||||
int readable ;
|
||||
} qfits_col ;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Table object
|
||||
|
||||
This structure contains all information needed to read a FITS table.
|
||||
These information come from the header. The object is created by
|
||||
qfits_open().
|
||||
|
||||
To read a FITS table, here is a code example:
|
||||
@code
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
qfits_table * table ;
|
||||
int n_ext ;
|
||||
int i ;
|
||||
|
||||
n_ext = qfits_query_n_ext(argv[1]);
|
||||
for (i=0 ; i<n_ext ; i++) {
|
||||
if ((table = qfits_table_open(argv[1], i+1)) == NULL) {
|
||||
printf("cannot open table [%s]:[%d]\n", argv[1], i+1);
|
||||
} else {
|
||||
dump_extension(table, stdout, '|', 1, 1) ;
|
||||
qfits_table_close(table) ;
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
typedef struct _qfits_table_
|
||||
{
|
||||
/**
|
||||
Name of the file the table comes from or it is intended to end to
|
||||
*/
|
||||
char filename[FILENAMESZ] ;
|
||||
/**
|
||||
Table type. Possible values are QFITS_INVALIDTABLE, QFITS_BINTABLE
|
||||
or QFITS_ASCIITABLE
|
||||
*/
|
||||
int tab_t ;
|
||||
/**
|
||||
Number of columns
|
||||
*/
|
||||
int nc ;
|
||||
/**
|
||||
Array of qfits_col objects
|
||||
*/
|
||||
qfits_col * col ;
|
||||
} qfits_table ;
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Function prototypes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Identify a file as containing a FITS table in extension.
|
||||
@param filename Name of the FITS file to examine.
|
||||
@param xtnum Extension number to check (starting from 1).
|
||||
@return int 1 if the extension contains a table, 0 else.
|
||||
|
||||
Examines the requested extension and identifies the presence of a
|
||||
FITS table.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_is_table(char * filename, int xtnum) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Read a FITS extension.
|
||||
@param filename Name of the FITS file to examine.
|
||||
@param xtnum Extension number to read (starting from 1).
|
||||
@return Pointer to newly allocated qfits_table structure.
|
||||
|
||||
Read a FITS table from a given file name and extension, and return a
|
||||
newly allocated qfits_table structure. This structure contains the
|
||||
following informations:
|
||||
- Name of the FITS file associated to table
|
||||
- Table type
|
||||
- Number of columns in table
|
||||
- Array of qfits_col objects
|
||||
|
||||
The table type is an int taking the following values:
|
||||
- QFITS_BINTABLE for binary tables
|
||||
- QFITS_ASCIITABLE for ascii tables
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
qfits_table * qfits_table_open(char * filename, int xtnum) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Free a FITS table and associated pointers
|
||||
@param t qfits_table to free
|
||||
@return void
|
||||
Frees all memory associated to a qfits_table structure.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void qfits_table_close(qfits_table * t) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Extract data from a column in a FITS table
|
||||
@param th Allocated qfits_table
|
||||
@param colnum Number of the column to extract (from 0 to colnum-1)
|
||||
@return unsigned char array
|
||||
|
||||
Extract a column from a FITS table and return the data as a bytes
|
||||
array. The returned array type and size are determined by the
|
||||
column object in the qfits_table.
|
||||
|
||||
Returned array size in bytes is:
|
||||
col->nelem * col->natoms * col->atom_size
|
||||
|
||||
Numeric types are correctly understood and byte-swapped if needed,
|
||||
to be converted to the local machine type.
|
||||
|
||||
NULL values have to be handled by the caller
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
unsigned char * qfits_query_column(
|
||||
qfits_table * th,
|
||||
int colnum) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Extract binary data from a column in a FITS table
|
||||
@param th Allocated qfits_table
|
||||
@param colnum Number of the column to extract (from 0 to colnum-1)
|
||||
@param null_value Value to return when a NULL value comes
|
||||
@return Pointer to void *
|
||||
|
||||
Extract a column from a FITS table and return the data as a generic
|
||||
void* array. The returned array type and size are determined by the
|
||||
column object in the qfits_table.
|
||||
|
||||
Returned array size in bytes is:
|
||||
col->nelem * col->atom_nb * col->atom_size
|
||||
|
||||
NULL values are recognized and replaced by the specified value.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void * qfits_query_column_data(
|
||||
qfits_table * th,
|
||||
int colnum,
|
||||
void * null_value) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief Save a table to a FITS file with a given FITS header.
|
||||
@param array Data array.
|
||||
@param table table
|
||||
@param filename Name of the image on disk.
|
||||
@param fh FITS header to insert in the output file.
|
||||
@return -1 in error case, 0 otherwise
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int qfits_save_table_hdrdump(
|
||||
void ** array,
|
||||
qfits_table * table,
|
||||
char * filename,
|
||||
qfits_header * fh) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief given a col and a row, find out the string to write for display
|
||||
@param table table structure
|
||||
@param col_id col id (0 -> nbcol-1)
|
||||
@param row_id row id (0 -> nrow-1)
|
||||
@param column array that contains the column data
|
||||
@param use_zero_scale Flag to use or not zero and scale
|
||||
@return the string to write
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_table_field_to_string(
|
||||
qfits_table * table,
|
||||
int col_id,
|
||||
int row_id,
|
||||
void * column,
|
||||
int use_zero_scale) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief given a col and a row, find out the string to write for display
|
||||
@param table table structure
|
||||
@param col_id col id (0 -> nbcol-1)
|
||||
@param row_id row id (0 -> nrow-1)
|
||||
@param column array that contains the column data
|
||||
@param use_zero_scale Flag to use or not zero and scale
|
||||
@return the string to write
|
||||
|
||||
ASCII tables specific
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_asciitable_field_to_string(
|
||||
qfits_table * table,
|
||||
int col_id,
|
||||
int row_id,
|
||||
void * column,
|
||||
int use_zero_scale) ;
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/**
|
||||
@brief given a col and a row, find out the string to write for display
|
||||
@param table table structure
|
||||
@param col_id col id (0 -> nbcol-1)
|
||||
@param row_id row id (0 -> nrow-1)
|
||||
@param column array that contains the column data
|
||||
@param use_zero_scale Flag to use or not zero and scale
|
||||
@return the string to write
|
||||
|
||||
BIN tables specific
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char * qfits_bintable_field_to_string(
|
||||
qfits_table * table,
|
||||
int col_id,
|
||||
int row_id,
|
||||
void * column,
|
||||
int use_zero_scale) ;
|
||||
|
||||
/* </dox> */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
/* Library version */
|
||||
static char *
|
||||
_qfits_version = "4.0.2" ;
|
||||
|
||||
char * qfits_version(void)
|
||||
{
|
||||
return _qfits_version ;
|
||||
}
|
||||
/* vim: set ts=4 et sw=4 tw=75 */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,759 @@
|
|||
|
||||
/*---------------------------------------------------------------------------
|
||||
|
||||
File name : sysconf.c
|
||||
Author : Nicolas Devillard
|
||||
Created on : February 2001
|
||||
Description : configure-like in C.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: sysconf.c,v 1.17 2002/01/22 14:47:55 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/22 14:47:55 $
|
||||
$Revision: 1.17 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#define MAXSTRSZ 512
|
||||
|
||||
#define MACROS_FILE "config.make"
|
||||
#define HEADER_FILE "config.h"
|
||||
#define PREFIX_DEFAULT "/opt/qfits"
|
||||
|
||||
#define COMPILER_AUTO 0
|
||||
#define COMPILER_CC 1
|
||||
#define COMPILER_GCC 2
|
||||
|
||||
/* Global variable */
|
||||
|
||||
struct {
|
||||
/* List of supported OS's */
|
||||
enum {
|
||||
os_linux,
|
||||
os_hp08,
|
||||
os_hp09,
|
||||
os_hp10,
|
||||
os_hp11,
|
||||
os_solaris,
|
||||
os_aix,
|
||||
os_dec,
|
||||
os_bsd,
|
||||
os_darwin
|
||||
} local_os ;
|
||||
char sysname[MAXSTRSZ];
|
||||
char release[MAXSTRSZ];
|
||||
char machine[MAXSTRSZ];
|
||||
|
||||
/* Bits per byte on this machine */
|
||||
int bits_per_byte ;
|
||||
/* Big endian machine? */
|
||||
int big_endian ;
|
||||
|
||||
/* x86 architecture? */
|
||||
int arch_x86 ;
|
||||
/* CPU type: 386, 486, 586, 686 */
|
||||
int cpu_x86 ;
|
||||
|
||||
/* Compile with debug options on */
|
||||
int debug_compile ;
|
||||
/* Compile with warnings on */
|
||||
int lint_compile ;
|
||||
/* Compiler type: native cc or gcc */
|
||||
int compiler ;
|
||||
/* Compile with tracing (gcc only >= 2.95) */
|
||||
int with_trace ;
|
||||
/* Compile with threads */
|
||||
int with_threads ;
|
||||
/* Number of detected CPUs */
|
||||
int ncpus ;
|
||||
/* Compile with gcc3 (pollux only) */
|
||||
int gcc3 ;
|
||||
/* Compile static library */
|
||||
int lib_static ;
|
||||
/* Compile dynamic library */
|
||||
int lib_dynamic ;
|
||||
/* Prefix for installation */
|
||||
char * prefix ;
|
||||
} config ;
|
||||
|
||||
|
||||
|
||||
/* Guess local OS name and potentially release number */
|
||||
detect_config()
|
||||
{
|
||||
struct utsname name ;
|
||||
int i ;
|
||||
unsigned char c ;
|
||||
int x ;
|
||||
|
||||
if (config.sysname[0]==0) {
|
||||
printf("detecting local OS............. ");
|
||||
/* Get machine OS type and release number */
|
||||
if (uname(&name)==-1) {
|
||||
printf("error calling uname\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf("%s %s", name.sysname, name.release);
|
||||
strcpy(config.sysname, name.sysname);
|
||||
strcpy(config.release, name.release);
|
||||
strcpy(config.machine, name.machine);
|
||||
} else {
|
||||
printf("forcing config for OS.......... %s %s",
|
||||
config.sysname,
|
||||
config.release);
|
||||
}
|
||||
|
||||
/* Lowercase everything */
|
||||
i=0 ;
|
||||
while(config.sysname[i]!=0) {
|
||||
config.sysname[i] = tolower(config.sysname[i]);
|
||||
i++ ;
|
||||
}
|
||||
i=0 ;
|
||||
while(config.release[i]!=0) {
|
||||
config.release[i] = tolower(config.release[i]);
|
||||
i++ ;
|
||||
}
|
||||
|
||||
/* Switch on OS type and release number */
|
||||
if (strstr(config.sysname, "linux")!=NULL) {
|
||||
config.local_os = os_linux ;
|
||||
printf(" - linux\n");
|
||||
} else if (strstr(config.sysname, "hp")!=NULL) {
|
||||
if (strstr(config.release, "8.")!=NULL) {
|
||||
config.local_os = os_hp08 ;
|
||||
printf(" - hpux_08\n");
|
||||
} else if (strstr(config.release, "9.")!=NULL) {
|
||||
config.local_os = os_hp09 ;
|
||||
printf(" - hpux_09\n");
|
||||
} else if (strstr(config.release, "10.")!=NULL) {
|
||||
config.local_os = os_hp10 ;
|
||||
printf(" - hpux_10\n");
|
||||
} else if (strstr(config.release, "11.")!=NULL) {
|
||||
config.local_os = os_hp11 ;
|
||||
printf(" - hpux_11\n");
|
||||
}
|
||||
} else if ((strstr(config.sysname, "sun")!=NULL) ||
|
||||
(strstr(config.sysname, "solaris")!=NULL)) {
|
||||
config.local_os = os_solaris ;
|
||||
printf(" - solaris\n");
|
||||
} else if (strstr(config.sysname, "aix")!=NULL) {
|
||||
config.local_os = os_aix ;
|
||||
printf(" - aix\n");
|
||||
} else if (strstr(config.sysname, "osf")!=NULL) {
|
||||
config.local_os = os_dec ;
|
||||
printf(" - osf/1\n");
|
||||
} else if (strstr(config.sysname, "bsd")!=NULL) {
|
||||
config.local_os = os_bsd ;
|
||||
printf(" - %s\n", config.sysname);
|
||||
} else if (strstr(config.sysname, "darwin")!=NULL) {
|
||||
config.local_os = os_darwin ;
|
||||
printf(" - %s\n", config.sysname);
|
||||
} else {
|
||||
printf("cannot identify your OS\n");
|
||||
printf("Use the option --os=NAME to force an OS type\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Find out about x86 architectures */
|
||||
if ((config.machine[0]=='i') && (strstr(config.machine, "86")!=NULL)) {
|
||||
config.arch_x86 = 1 ;
|
||||
config.cpu_x86 = atoi(config.machine+1) ;
|
||||
printf("detected x86 architecture...... %d\n", config.cpu_x86);
|
||||
} else {
|
||||
config.arch_x86 = 0 ;
|
||||
printf("detected x86 architecture...... no\n");
|
||||
}
|
||||
|
||||
|
||||
/* Compute number of bits in a byte on this machine */
|
||||
printf("computing bits per byte........ ");
|
||||
c=1 ; i=0 ;
|
||||
while (c) {
|
||||
c<<=1 ; i++ ;
|
||||
}
|
||||
config.bits_per_byte = i ;
|
||||
printf("%d\n", i);
|
||||
|
||||
/* Detect endian-ness */
|
||||
printf("detecting byte-order........... ");
|
||||
x = 1 ;
|
||||
x = (*(char*)&x) ;
|
||||
|
||||
config.big_endian = !x ;
|
||||
if (config.big_endian) {
|
||||
printf("big endian (motorola)\n");
|
||||
} else {
|
||||
printf("little endian (intel)\n");
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/* Locate a program in the user's PATH */
|
||||
int locate_program(pname)
|
||||
char * pname ;
|
||||
{
|
||||
int i, j, lg;
|
||||
char * path ;
|
||||
char buf[MAXSTRSZ];
|
||||
|
||||
path = getenv("PATH");
|
||||
if (path!=NULL) {
|
||||
for (i=0; path[i]; ) {
|
||||
for (j=i ; (path[j]) && (path[j]!=':') ; j++);
|
||||
lg = j - i;
|
||||
strncpy(buf, path + i, lg);
|
||||
if (lg == 0) buf[lg++] = '.';
|
||||
buf[lg++] = '/';
|
||||
strcpy(buf + lg, pname);
|
||||
if (access(buf, X_OK) == 0) {
|
||||
printf("using [%s]\n", buf);
|
||||
return 1 ;
|
||||
}
|
||||
buf[0] = 0;
|
||||
i = j;
|
||||
if (path[i] == ':') i++ ;
|
||||
}
|
||||
} else {
|
||||
/* No PATH variable: abort with an error */
|
||||
return -1 ;
|
||||
}
|
||||
/* If the buffer is still empty, the command was not found */
|
||||
if (buf[0] == 0) return 0 ;
|
||||
/* Otherwise Ok */
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
make_config_make()
|
||||
{
|
||||
FILE * sysc ;
|
||||
|
||||
/* Set compiler name */
|
||||
printf("looking for a C compiler....... ");
|
||||
if (getenv("PATH")==NULL) {
|
||||
printf("error: undefined PATH variable, cannot locate a compiler\n");
|
||||
exit(-1) ;
|
||||
}
|
||||
|
||||
/* Open output sysconf */
|
||||
if ((sysc=fopen(MACROS_FILE, "w"))==NULL) {
|
||||
printf("cannot create %s: aborting compilation", MACROS_FILE);
|
||||
exit(-1) ;
|
||||
}
|
||||
|
||||
/* In automatic mode, find out which compiler to use */
|
||||
if (config.compiler==COMPILER_AUTO) {
|
||||
switch (config.local_os) {
|
||||
|
||||
/* Linux and BSD use gcc always */
|
||||
case os_linux:
|
||||
case os_bsd:
|
||||
config.compiler = COMPILER_GCC ;
|
||||
break ;
|
||||
|
||||
/* All others use 'cc' (default) */
|
||||
default:
|
||||
config.compiler = COMPILER_CC ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Make sure the compiler can be found */
|
||||
if (config.compiler==COMPILER_CC) {
|
||||
if (locate_program("cc")!=1) {
|
||||
printf("cannot locate cc\n");
|
||||
/* Try out with gcc */
|
||||
config.compiler = COMPILER_GCC ;
|
||||
}
|
||||
}
|
||||
if (config.compiler==COMPILER_GCC) {
|
||||
if (locate_program("gcc")!=1) {
|
||||
printf("cannot locate gcc\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set compiler name and cflags */
|
||||
switch (config.compiler) {
|
||||
|
||||
case COMPILER_CC:
|
||||
fprintf(sysc, "CC = cc\n");
|
||||
fprintf(sysc, "CFLAGS = ");
|
||||
switch (config.local_os) {
|
||||
case os_hp08:
|
||||
case os_hp09:
|
||||
case os_hp10:
|
||||
if (config.with_threads) {
|
||||
printf("threads not supported on this platform\n");
|
||||
}
|
||||
if (config.debug_compile) {
|
||||
fprintf(sysc, "-Ae -g\n");
|
||||
} else {
|
||||
fprintf(sysc, "-Ae -O\n");
|
||||
}
|
||||
fprintf(sysc, "RELOC = +z\n");
|
||||
fprintf(sysc, "SHARED = -b\n");
|
||||
break ;
|
||||
|
||||
case os_hp11:
|
||||
if (config.with_threads) {
|
||||
fprintf(sysc, "-lpthread ");
|
||||
}
|
||||
if (config.debug_compile) {
|
||||
fprintf(sysc, "-g\n");
|
||||
} else {
|
||||
fprintf(sysc, "-O\n");
|
||||
}
|
||||
fprintf(sysc, "RELOC = +z\n");
|
||||
fprintf(sysc, "SHARED = -b\n");
|
||||
break ;
|
||||
|
||||
case os_solaris:
|
||||
if (config.with_threads) {
|
||||
fprintf(sysc, "-mt -lpthread ");
|
||||
}
|
||||
if (config.debug_compile) {
|
||||
fprintf(sysc, "-g\n");
|
||||
} else {
|
||||
fprintf(sysc, "-xO5\n");
|
||||
}
|
||||
fprintf(sysc, "RELOC = -G\n");
|
||||
fprintf(sysc, "SHARED = -G\n");
|
||||
break ;
|
||||
|
||||
case os_dec:
|
||||
if (config.with_threads) {
|
||||
printf("threads not supported on this platform\n");
|
||||
}
|
||||
if (config.debug_compile) {
|
||||
fprintf(sysc, "-g\n");
|
||||
} else {
|
||||
fprintf(sysc, "-O\n");
|
||||
}
|
||||
fprintf(sysc, "RELOC =\n");
|
||||
fprintf(sysc, "SHARED = -shared -expect_unresolved \"*\"\n");
|
||||
break ;
|
||||
|
||||
case os_aix:
|
||||
case os_bsd:
|
||||
if (config.with_threads) {
|
||||
printf("threads not supported on this platform\n");
|
||||
}
|
||||
if (config.debug_compile) {
|
||||
fprintf(sysc, "-g\n");
|
||||
} else {
|
||||
fprintf(sysc, "-O\n");
|
||||
}
|
||||
fprintf(sysc, "RELOC =\n");
|
||||
fprintf(sysc, "SHARED =\n");
|
||||
break ;
|
||||
|
||||
case os_linux:
|
||||
/* cc with Linux? Why not! */
|
||||
if (config.with_threads) {
|
||||
fprintf(sysc, "-pthread ");
|
||||
}
|
||||
if (config.debug_compile) {
|
||||
fprintf(sysc, "-g\n");
|
||||
} else {
|
||||
fprintf(sysc, "-O3\n");
|
||||
}
|
||||
fprintf(sysc, "RELOC = -fpic\n");
|
||||
fprintf(sysc, "SHARED = -shared\n");
|
||||
break ;
|
||||
|
||||
case os_darwin:
|
||||
/* Darwin uses gcc but calls it 'cc' */
|
||||
fprintf(sysc, "-DOS_DARWIN=1 -Dsrand48=srandom -Ddrand48=random ");
|
||||
if (config.with_threads) {
|
||||
fprintf(sysc, "-pthread ");
|
||||
}
|
||||
if (config.debug_compile) {
|
||||
fprintf(sysc, "-g\n");
|
||||
} else {
|
||||
fprintf(sysc, "-O3\n");
|
||||
}
|
||||
fprintf(sysc, "RELOC = -fPIC\n");
|
||||
fprintf(sysc, "SHARED = -shared\n");
|
||||
break ;
|
||||
|
||||
|
||||
default:
|
||||
printf("error: unsupported OS\n");
|
||||
exit(-1) ;
|
||||
}
|
||||
break ;
|
||||
|
||||
case COMPILER_GCC:
|
||||
if (config.gcc3) {
|
||||
fprintf(sysc, "CC = /opt/gcc3/bin/gcc\n");
|
||||
} else {
|
||||
fprintf(sysc, "CC = gcc\n");
|
||||
}
|
||||
fprintf(sysc, "CFLAGS = ");
|
||||
if (config.with_threads) {
|
||||
fprintf(sysc, "-pthread ");
|
||||
}
|
||||
if (config.lint_compile) {
|
||||
fprintf(sysc, " -Wall -pedantic ");
|
||||
}
|
||||
if (config.debug_compile) {
|
||||
fprintf(sysc, "-g\n");
|
||||
} else {
|
||||
fprintf(sysc, "-O3\n");
|
||||
}
|
||||
if (config.with_trace) {
|
||||
fprintf(sysc, "FTRACE = -finstrument-functions\n");
|
||||
} else {
|
||||
fprintf(sysc, "FTRACE =\n");
|
||||
}
|
||||
fprintf(sysc, "RELOC = -fpic\n");
|
||||
fprintf(sysc, "SHARED = -shared\n");
|
||||
break ;
|
||||
|
||||
default:
|
||||
printf("error in compiler option switch: aborting\n");
|
||||
exit(-1);
|
||||
break ;
|
||||
}
|
||||
|
||||
if (config.debug_compile) {
|
||||
printf(" in debug mode\n");
|
||||
} else {
|
||||
printf(" all optimizations on\n");
|
||||
}
|
||||
if (config.lint_compile) {
|
||||
printf(" with all warnings\n");
|
||||
}
|
||||
if (config.with_trace) {
|
||||
printf(" with function tracing\n");
|
||||
}
|
||||
|
||||
/* LFLAGS */
|
||||
switch (config.local_os) {
|
||||
|
||||
case os_hp10:
|
||||
case os_hp11:
|
||||
fprintf(sysc, "# Shut up HPUX 11 linker\n");
|
||||
fprintf(sysc, "LFLAGS = -Wl,+vnocompatwarnings\n");
|
||||
break ;
|
||||
|
||||
default:
|
||||
fprintf(sysc, "LFLAGS =\n");
|
||||
break ;
|
||||
}
|
||||
|
||||
/* RANLIB */
|
||||
switch (config.local_os) {
|
||||
case os_hp08:
|
||||
case os_hp09:
|
||||
case os_hp10:
|
||||
case os_hp11:
|
||||
fprintf(sysc, "RANLIB = ranlib\n");
|
||||
fprintf(sysc, "DYNSUF = sl\n");
|
||||
break ;
|
||||
|
||||
case os_darwin:
|
||||
fprintf(sysc, "RANLIB = ranlib\n");
|
||||
fprintf(sysc, "DYNSUF = so\n");
|
||||
break ;
|
||||
|
||||
|
||||
default:
|
||||
fprintf(sysc, "RANLIB = true\n");
|
||||
fprintf(sysc, "DYNSUF = so\n");
|
||||
break ;
|
||||
}
|
||||
|
||||
/* STRIP */
|
||||
if (config.debug_compile) {
|
||||
fprintf(sysc, "STRIP = true\n");
|
||||
} else {
|
||||
fprintf(sysc, "STRIP = strip\n");
|
||||
}
|
||||
|
||||
/* TARGETS */
|
||||
fprintf(sysc, "TARGETS =");
|
||||
printf("static library................. %s\n",
|
||||
config.lib_static ? "yes" : "no");
|
||||
if (config.lib_static) {
|
||||
fprintf(sysc, " static");
|
||||
}
|
||||
printf("shared library................. %s\n",
|
||||
config.lib_dynamic ? "yes" : "no");
|
||||
if (config.lib_dynamic) {
|
||||
fprintf(sysc, " dynamic");
|
||||
}
|
||||
fprintf(sysc,"\n");
|
||||
|
||||
/* PREFIX */
|
||||
fprintf(sysc, "prefix = %s\n",
|
||||
config.prefix ? config.prefix : PREFIX_DEFAULT);
|
||||
printf("setting installation prefix as: [%s]\n",
|
||||
config.prefix ? config.prefix : PREFIX_DEFAULT);
|
||||
fclose(sysc);
|
||||
}
|
||||
|
||||
|
||||
make_config_h()
|
||||
{
|
||||
FILE * out ;
|
||||
|
||||
out = fopen(HEADER_FILE, "w");
|
||||
if (out==NULL) {
|
||||
printf("cannot create header file %s: aborting", HEADER_FILE);
|
||||
return ;
|
||||
}
|
||||
|
||||
fprintf(out,
|
||||
"/* This file automatically generated */\n"
|
||||
"#ifndef _CONFIG_H_\n"
|
||||
"#define _CONFIG_H_\n"
|
||||
"\n"
|
||||
"%s",
|
||||
config.big_endian ? "#define WORDS_BIGENDIAN 1\n" : "\n"
|
||||
);
|
||||
|
||||
/* Generate SIZEOF macros for basic types */
|
||||
printf("detecting basic size types\n");
|
||||
fprintf(out,
|
||||
"#define SIZEOF_CHAR %d\n"
|
||||
"#define SIZEOF_SHORT %d\n"
|
||||
"#define SIZEOF_INT %d\n"
|
||||
"#define SIZEOF_LONG %d\n"
|
||||
"#define SIZEOF_FLOAT %d\n"
|
||||
"#define SIZEOF_DOUBLE %d\n",
|
||||
sizeof(char),
|
||||
sizeof(short),
|
||||
sizeof(int),
|
||||
sizeof(long),
|
||||
sizeof(float),
|
||||
sizeof(double));
|
||||
printf(
|
||||
"sizeof(char)................... %d\n"
|
||||
"sizeof(short).................. %d\n"
|
||||
"sizeof(int).................... %d\n"
|
||||
"sizeof(long)................... %d\n"
|
||||
"sizeof(float).................. %d\n"
|
||||
"sizeof(double)................. %d\n",
|
||||
sizeof(char),
|
||||
sizeof(short),
|
||||
sizeof(int),
|
||||
sizeof(long),
|
||||
sizeof(float),
|
||||
sizeof(double));
|
||||
|
||||
/* Do not output CHAR_BIT on AIX */
|
||||
if (config.local_os!=os_aix) {
|
||||
fprintf(out,
|
||||
"\n"
|
||||
"#ifndef CHAR_BIT\n"
|
||||
"#define CHAR_BIT\t%d\n"
|
||||
"#endif\n"
|
||||
"\n\n",
|
||||
config.bits_per_byte);
|
||||
}
|
||||
|
||||
if (config.arch_x86) {
|
||||
fprintf(out, "#define CPU_X86 %d\n", config.cpu_x86);
|
||||
}
|
||||
|
||||
if (config.with_threads) {
|
||||
fprintf(out, "#define HAS_PTHREADS 1\n\n");
|
||||
}
|
||||
switch (config.local_os) {
|
||||
case os_hp08:
|
||||
case os_hp09:
|
||||
case os_hp10:
|
||||
case os_hp11:
|
||||
fprintf(out, "#define OS_HPUX 1\n");
|
||||
break ;
|
||||
|
||||
case os_linux:
|
||||
fprintf(out, "#define OS_LINUX 1\n");
|
||||
break ;
|
||||
|
||||
case os_aix:
|
||||
fprintf(out, "#define OS_AIX 1\n");
|
||||
break ;
|
||||
|
||||
case os_dec:
|
||||
fprintf(out, "#define OS_DEC 1\n");
|
||||
break ;
|
||||
|
||||
case os_solaris:
|
||||
fprintf(out, "#define OS_SOLARIS 1\n");
|
||||
break ;
|
||||
|
||||
case os_bsd:
|
||||
fprintf(out, "#define OS_BSD 1\n");
|
||||
break ;
|
||||
|
||||
case os_darwin:
|
||||
fprintf(out, "#define OS_DARWIN 1\n");
|
||||
break ;
|
||||
|
||||
default:
|
||||
fprintf(out, "#define OS_UNKNOWN 1\n");
|
||||
break ;
|
||||
}
|
||||
fprintf(out, "#endif\n");
|
||||
fclose(out);
|
||||
printf("done\n");
|
||||
return ;
|
||||
|
||||
}
|
||||
|
||||
help()
|
||||
{
|
||||
printf(
|
||||
"\n\n"
|
||||
"***** qfits configure help\n"
|
||||
"Use: configure [options]\n"
|
||||
"\n"
|
||||
"options are:\n"
|
||||
"\t--debug Compile modules in debug mode\n"
|
||||
"\t--help Get this help\n"
|
||||
"\n"
|
||||
"\t--with-cc Force compilation with local cc\n"
|
||||
"\t--with-gcc Force compilation with gcc\n"
|
||||
"\n"
|
||||
"\t--enable-static Compile static library (default)\n"
|
||||
"\t--enable-shared Compile shared library\n"
|
||||
"\t--disable-shared Do not compile shared library (default)\n"
|
||||
"\t--disable-static Do not compile static library\n"
|
||||
"\n"
|
||||
"\t--prefix=PATH Install in PATH (must be absolute)\n"
|
||||
"\t--mt Compile with multithreading support\n"
|
||||
"\n"
|
||||
"options specific to compilation with gcc (for developers):\n"
|
||||
"\t--lint Compile with -Wall\n"
|
||||
"\t--trace Compile function tracing capabilities\n"
|
||||
"\t--gcc3 Compile with gcc3 in /opt/gcc3\n"
|
||||
"\n"
|
||||
"If your platform is not or incorrectly recognized, you\n"
|
||||
"can force a given configuration with this option:\n"
|
||||
"\n"
|
||||
"\t--os=NAME Where NAME is one of the following:\n"
|
||||
"\n"
|
||||
"\tlinux - Linux systems (any processor type)\n"
|
||||
"\thp08 - HPUX version 8.x\n"
|
||||
"\thp09 - HPUX version 9.x\n"
|
||||
"\thp10 - HPUX version 10.x\n"
|
||||
"\thp11 - HPUX version 11.x\n"
|
||||
"\taix - IBM AIX (any version)\n"
|
||||
"\tdec - Dec OSF/1 or Tru64 Unix\n"
|
||||
"\tsolaris - Sun Solaris >=2.5\n"
|
||||
"\tbsd - BSD compatible Unix\n"
|
||||
"\tdarwin - Darwin (BSD compatible on Mac)\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
int main(argc, argv)
|
||||
int argc ;
|
||||
char * argv[];
|
||||
{
|
||||
char sysname[MAXSTRSZ];
|
||||
int i ;
|
||||
|
||||
config.debug_compile = 0;
|
||||
config.lint_compile = 0 ;
|
||||
config.compiler = COMPILER_AUTO ;
|
||||
config.with_threads = 0 ;
|
||||
config.with_trace = 0 ;
|
||||
config.gcc3 = 0 ;
|
||||
config.lib_static = 1 ;
|
||||
config.lib_dynamic = 0 ;
|
||||
config.prefix = NULL ;
|
||||
|
||||
memset(config.sysname, 0, MAXSTRSZ);
|
||||
memset(config.release, 0, MAXSTRSZ);
|
||||
memset(config.machine, 0, MAXSTRSZ);
|
||||
|
||||
for (i=0 ; i<argc ; i++) {
|
||||
if (!strcmp(argv[i], "--help")) {
|
||||
help() ;
|
||||
return 1 ;
|
||||
} else if (!strcmp(argv[i], "--debug")) {
|
||||
config.debug_compile = 1 ;
|
||||
} else if (!strcmp(argv[i], "--with-cc")) {
|
||||
config.compiler = COMPILER_CC ;
|
||||
} else if (!strcmp(argv[i], "--with-gcc")) {
|
||||
config.compiler = COMPILER_GCC ;
|
||||
} else if (!strcmp(argv[i], "--lint")) {
|
||||
config.lint_compile = 1 ;
|
||||
} else if (!strcmp(argv[i], "--mt")) {
|
||||
config.with_threads=1 ;
|
||||
} else if (!strcmp(argv[i], "--trace")) {
|
||||
config.with_trace = 1 ;
|
||||
} else if (!strcmp(argv[i], "--gcc3")) {
|
||||
config.gcc3=1 ;
|
||||
} else if (!strcmp(argv[i], "--enable-shared")) {
|
||||
config.lib_dynamic = 1;
|
||||
} else if (!strcmp(argv[i], "--disable-shared")) {
|
||||
config.lib_dynamic = 0;
|
||||
} else if (!strcmp(argv[i], "--enable-static")) {
|
||||
config.lib_static = 1;
|
||||
} else if (!strcmp(argv[i], "--disable-static")) {
|
||||
config.lib_static = 0;
|
||||
} else if (!strncmp(argv[i], "--prefix=", 9)) {
|
||||
config.prefix = strchr(argv[i], '=') + 1 ;
|
||||
} else if (!strncmp(argv[i], "--os=", 5)) {
|
||||
strcpy(sysname, argv[i]+5);
|
||||
if (!strcmp(sysname, "linux")) {
|
||||
strcpy(config.sysname, "Linux");
|
||||
} else if (!strcmp(sysname, "hp08")) {
|
||||
strcpy(config.sysname, "HPUX");
|
||||
strcpy(config.release, "8.x");
|
||||
} else if (!strcmp(sysname, "hp09")) {
|
||||
strcpy(config.sysname, "HPUX");
|
||||
strcpy(config.release, "9.x");
|
||||
} else if (!strcmp(sysname, "hp10")) {
|
||||
strcpy(config.sysname, "HPUX");
|
||||
strcpy(config.release, "10.x");
|
||||
} else if (!strcmp(sysname, "hp11")) {
|
||||
strcpy(config.sysname, "HPUX");
|
||||
strcpy(config.release, "11.x");
|
||||
} else if (!strcmp(sysname, "aix")) {
|
||||
strcpy(config.sysname, "AIX");
|
||||
} else if (!strcmp(sysname, "dec")) {
|
||||
strcpy(config.sysname, "Dec OSF/1 or Tru64");
|
||||
} else if (!strcmp(sysname, "solaris")) {
|
||||
strcpy(config.sysname, "Solaris");
|
||||
strcpy(config.release, ">= 2.5");
|
||||
} else if (!strcmp(sysname, "bsd")) {
|
||||
strcpy(config.sysname, "BSD compatible");
|
||||
} else if (!strcmp(sysname, "darwin")) {
|
||||
strcpy(config.sysname, "Darwin");
|
||||
} else {
|
||||
printf("unsupported OS: %s\n", sysname);
|
||||
return -1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
detect_config();
|
||||
make_config_make();
|
||||
make_config_h();
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# Makefile for qfits test modules
|
||||
#
|
||||
|
||||
include ../config.make
|
||||
|
||||
RM = rm -f
|
||||
|
||||
# Compile rules
|
||||
|
||||
SUFFIXES = .o .c .h .a .so .sl
|
||||
|
||||
COMPILE.c = $(CC) $(CFLAGS) $(FTRACE) -L../lib -I../include -o $@ $< -lqfits $(LFLAGS)
|
||||
.c:
|
||||
$(COMPILE.c)
|
||||
|
||||
default: all
|
||||
|
||||
all: test_qfits
|
||||
|
||||
clean veryclean:
|
||||
$(RM) test_qfits
|
||||
|
|
@ -0,0 +1,768 @@
|
|||
|
||||
/*---------------------------------------------------------------------------
|
||||
qfits test suite
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
$Id: test_qfits.c,v 1.4 2002/01/15 15:10:59 ndevilla Exp $
|
||||
$Author: ndevilla $
|
||||
$Date: 2002/01/15 15:10:59 $
|
||||
$Revision: 1.4 $
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Includes
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "qfits.h"
|
||||
#include "xmemory.h"
|
||||
|
||||
#define QFITSTESTFILENAME "QFITS.fits"
|
||||
#define BINDUMPNAME "bindump.dat"
|
||||
|
||||
#define say(s) fprintf(stderr, "qtest:\t\t%s\n", s)
|
||||
#define _fail(s,l) fprintf(stderr, "qtest(%d): %s\n", l, s)
|
||||
#define fail(s) _fail(s,__LINE__)
|
||||
|
||||
#define REFSIG "6569daba7b124febfa0cd7813f555774"
|
||||
|
||||
|
||||
typedef unsigned char byte ;
|
||||
|
||||
static float float_array_orig[] =
|
||||
{
|
||||
1.0, 2.0, 0.0, -1.0, -2.0, 1e-4, -1e-4, 1e-6, -1e-6,
|
||||
1.2345678, 3.1415926535, 19.71
|
||||
};
|
||||
|
||||
static byte float_array_byte[] =
|
||||
{
|
||||
0x3f, 0x80, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0xbf, 0x80, 0x00, 0x00,
|
||||
0xc0, 0x00, 0x00, 0x00,
|
||||
0x38, 0xd1, 0xb7, 0x17,
|
||||
0xb8, 0xd1, 0xb7, 0x17,
|
||||
0x35, 0x86, 0x37, 0xbd,
|
||||
0xb5, 0x86, 0x37, 0xbd,
|
||||
0x3f, 0x9e, 0x06, 0x51,
|
||||
0x40, 0x49, 0x0f, 0xdb,
|
||||
0x41, 0x9d, 0xae, 0x14
|
||||
};
|
||||
|
||||
static int int_array_orig[] =
|
||||
{
|
||||
-32768, -16384, -8192, -4096, -1023, 0,
|
||||
1023, 2048, 8191, 16387, 32767, 65536
|
||||
};
|
||||
|
||||
static byte int_array_byte[] =
|
||||
{
|
||||
0xff, 0xff, 0x80, 0x00,
|
||||
0xff, 0xff, 0xc0, 0x00,
|
||||
0xff, 0xff, 0xe0, 0x00,
|
||||
0xff, 0xff, 0xf0, 0x00,
|
||||
0xff, 0xff, 0xfc, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x03, 0xff,
|
||||
0x00, 0x00, 0x08, 0x00,
|
||||
0x00, 0x00, 0x1f, 0xff,
|
||||
0x00, 0x00, 0x40, 0x03,
|
||||
0x00, 0x00, 0x7f, 0xff,
|
||||
0x00, 0x01, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
static double double_array_orig[] =
|
||||
{
|
||||
1.0, 2.0, 0.0, -1.0, -2.0, 1e-4, -1e-4, 1e-6, -1e-6,
|
||||
1.2345678, 3.1415926535, 19.71
|
||||
};
|
||||
|
||||
static byte double_array_byte[] =
|
||||
{
|
||||
0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xbf, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3f, 0x1a, 0x36, 0xe2, 0xeb, 0x1c, 0x43, 0x2d,
|
||||
0xbf, 0x1a, 0x36, 0xe2, 0xeb, 0x1c, 0x43, 0x2d,
|
||||
0x3e, 0xb0, 0xc6, 0xf7, 0xa0, 0xb5, 0xed, 0x8d,
|
||||
0xbe, 0xb0, 0xc6, 0xf7, 0xa0, 0xb5, 0xed, 0x8d,
|
||||
0x3f, 0xf3, 0xc0, 0xca, 0x2a, 0x5b, 0x1d, 0x5d,
|
||||
0x40, 0x09, 0x21, 0xfb, 0x54, 0x41, 0x17, 0x44,
|
||||
0x40, 0x33, 0xb5, 0xc2, 0x8f, 0x5c, 0x28, 0xf6
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
main
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
int test_qfitsheader_create(void)
|
||||
{
|
||||
qfits_header * qh ;
|
||||
FILE * out ;
|
||||
|
||||
say("-----> Header creation test");
|
||||
/* Test qfits_header creation */
|
||||
say("creating blank header");
|
||||
qh = qfits_header_new();
|
||||
if (qh==NULL) {
|
||||
fail("qfits_header_new() failed");
|
||||
return 1 ;
|
||||
}
|
||||
say("destroying blank header");
|
||||
/* Destroy header now */
|
||||
qfits_header_destroy(qh);
|
||||
|
||||
/* Create minimal header (SIMPLE/END) */
|
||||
say("creating minimal header");
|
||||
qh = qfits_header_default();
|
||||
if (qh==NULL) {
|
||||
fail("qfits_header_default() failed");
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
say("inserting primary keywords");
|
||||
/* Insert XTENSION marker */
|
||||
qfits_header_add(qh, "EXTEND", "T", "xtension might be present", NULL);
|
||||
|
||||
/* Insert a string */
|
||||
qfits_header_add(qh, "KEY01", "value01", "comment 01", NULL);
|
||||
/* Insert an int */
|
||||
qfits_header_add(qh, "KEY02", "2", "comment 02", NULL);
|
||||
/* Insert a double */
|
||||
qfits_header_add(qh, "KEY03", "3.0", "comment 03", NULL);
|
||||
/* Insert a complex */
|
||||
qfits_header_add(qh, "KEY04", "4.0 4.2", "comment 04", NULL);
|
||||
/* Insert a boolean */
|
||||
qfits_header_add(qh, "KEY05", "T", "comment 05", NULL);
|
||||
|
||||
|
||||
say("inserting history keywords");
|
||||
/* Insert HISTORY keys */
|
||||
qfits_header_add(qh, "HISTORY", "1 history field", NULL, NULL);
|
||||
qfits_header_add(qh, "HISTORY", "2 history field", NULL, NULL);
|
||||
qfits_header_add(qh, "HISTORY", "3 history field", NULL, NULL);
|
||||
qfits_header_add(qh, "HISTORY", "4 history field", NULL, NULL);
|
||||
|
||||
say("inserting comment keywords");
|
||||
/* Insert COMMENT keys */
|
||||
qfits_header_add(qh, "COMMENT", "1 comment field", NULL, NULL);
|
||||
qfits_header_add(qh, "COMMENT", "2 comment field", NULL, NULL);
|
||||
qfits_header_add(qh, "COMMENT", "3 comment field", NULL, NULL);
|
||||
qfits_header_add(qh, "COMMENT", "4 comment field", NULL, NULL);
|
||||
|
||||
say("inserting hierarch keywords");
|
||||
/* Insert HIERARCH ESO keys in reverse DICB order */
|
||||
qfits_header_add(qh, "HIERARCH ESO NULL A", "0.0", "not DICB", NULL);
|
||||
qfits_header_add(qh, "HIERARCH ESO NULL B", "0.0", "not DICB", NULL);
|
||||
qfits_header_add(qh, "HIERARCH ESO NULL C", "0.0", "not DICB", NULL);
|
||||
|
||||
qfits_header_add(qh, "PRO.A", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "PRO.B", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "PRO.C", "0.0", "DICB compliant", NULL);
|
||||
|
||||
qfits_header_add(qh, "HIERARCH ESO LOG A", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "HIERARCH ESO LOG B", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "HIERARCH ESO LOG C", "0.0", "DICB compliant", NULL);
|
||||
|
||||
qfits_header_add(qh, "INS.A", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "INS.B", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "INS.C", "0.0", "DICB compliant", NULL);
|
||||
|
||||
qfits_header_add(qh, "HIERARCH ESO TEL A", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "HIERARCH ESO TEL B", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "HIERARCH ESO TEL C", "0.0", "DICB compliant", NULL);
|
||||
|
||||
qfits_header_add(qh, "GEN.A", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "GEN.B", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "GEN.C", "0.0", "DICB compliant", NULL);
|
||||
|
||||
qfits_header_add(qh, "HIERARCH ESO TPL A", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "HIERARCH ESO TPL B", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "HIERARCH ESO TPL C", "0.0", "DICB compliant", NULL);
|
||||
|
||||
qfits_header_add(qh, "OBS.A", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "OBS.B", "0.0", "DICB compliant", NULL);
|
||||
qfits_header_add(qh, "OBS.C", "0.0", "DICB compliant", NULL);
|
||||
|
||||
say("inserting mandatory keywords");
|
||||
/* Insert mandatory keys in reverse order */
|
||||
qfits_header_add(qh, "NAXIS2", "10", "NAXIS2 comment", NULL);
|
||||
qfits_header_add(qh, "NAXIS1", "11", "NAXIS1 comment", NULL);
|
||||
qfits_header_add(qh, "NAXIS", "2", "NAXIS comment", NULL);
|
||||
qfits_header_add(qh, "BITPIX", "-32", "BITPIX comment", NULL);
|
||||
|
||||
/* qfits_header_consoledump(qh); */
|
||||
|
||||
/* Dump header to file */
|
||||
say("opening file for output");
|
||||
out = fopen(QFITSTESTFILENAME, "w");
|
||||
if (out==NULL) {
|
||||
fail("cannot create test file");
|
||||
qfits_header_destroy(qh);
|
||||
return 1 ;
|
||||
}
|
||||
say("dumping header to file");
|
||||
if (qfits_header_dump(qh, out)!=0) {
|
||||
fail("cannot dump header");
|
||||
qfits_header_destroy(qh);
|
||||
return 1 ;
|
||||
}
|
||||
fclose(out);
|
||||
say("destroying built header");
|
||||
qfits_header_destroy(qh);
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
int check_key(qfits_header * qh, char * key, char * expval)
|
||||
{
|
||||
char * val ;
|
||||
int err=0 ;
|
||||
|
||||
val = qfits_header_getstr(qh, key);
|
||||
if (val==NULL) {
|
||||
fail("missing key in header");
|
||||
err++ ;
|
||||
} else {
|
||||
val = qfits_pretty_string(val);
|
||||
if (strcmp(val, expval)) {
|
||||
fail("wrong value for key in header");
|
||||
err++ ;
|
||||
}
|
||||
}
|
||||
return err ;
|
||||
}
|
||||
|
||||
int test_qfitsheader_read(void)
|
||||
{
|
||||
qfits_header * qh ;
|
||||
char * val ;
|
||||
int err ;
|
||||
int keytype ;
|
||||
|
||||
err=0 ;
|
||||
say("-----> Header reading test");
|
||||
/* Read header from source */
|
||||
say("reading header from file");
|
||||
qh = qfits_header_read(QFITSTESTFILENAME);
|
||||
if (qh==NULL) {
|
||||
fail("cannot read test file");
|
||||
return 1 ;
|
||||
}
|
||||
say("querying mandatory keys");
|
||||
err += check_key(qh, "SIMPLE", "T");
|
||||
err += check_key(qh, "NAXIS", "2");
|
||||
err += check_key(qh, "NAXIS1", "11");
|
||||
err += check_key(qh, "NAXIS2", "10");
|
||||
err += check_key(qh, "BITPIX", "-32");
|
||||
|
||||
say("querying base keys");
|
||||
err += check_key(qh, "KEY01", "value01");
|
||||
err += check_key(qh, "KEY02", "2");
|
||||
err += check_key(qh, "KEY03", "3.0");
|
||||
err += check_key(qh, "KEY04", "4.0 4.2");
|
||||
err += check_key(qh, "KEY05", "T");
|
||||
|
||||
say("checking key types");
|
||||
val = qfits_header_getstr(qh, "KEY01");
|
||||
keytype = qfits_get_type(val);
|
||||
if (keytype!=QFITS_STRING) {
|
||||
printf("val=[%s] type is %d\n", val, keytype);
|
||||
fail("wrong identified type for KEY01 (string)");
|
||||
err++;
|
||||
}
|
||||
val = qfits_header_getstr(qh, "KEY02");
|
||||
keytype = qfits_get_type(val);
|
||||
if (keytype!=QFITS_INT) {
|
||||
fail("wrong identified type for KEY02 (int)");
|
||||
err++;
|
||||
}
|
||||
val = qfits_header_getstr(qh, "KEY03");
|
||||
keytype = qfits_get_type(val);
|
||||
if (keytype!=QFITS_FLOAT) {
|
||||
fail("wrong identified type for KEY03 (float)");
|
||||
err++;
|
||||
}
|
||||
val = qfits_header_getstr(qh, "KEY04");
|
||||
keytype = qfits_get_type(val);
|
||||
if (keytype!=QFITS_COMPLEX) {
|
||||
fail("wrong identified type for KEY04 (complex)");
|
||||
err++;
|
||||
}
|
||||
val = qfits_header_getstr(qh, "KEY05");
|
||||
keytype = qfits_get_type(val);
|
||||
if (keytype!=QFITS_BOOLEAN) {
|
||||
fail("wrong identified type for KEY05 (boolean)");
|
||||
err++;
|
||||
}
|
||||
|
||||
say("querying hierarch keys");
|
||||
err += check_key(qh, "HIERARCH ESO PRO A", "0.0");
|
||||
err += check_key(qh, "PRO.B", "0.0");
|
||||
err += check_key(qh, "pro.c", "0.0");
|
||||
|
||||
err += check_key(qh, "ins.a", "0.0");
|
||||
err += check_key(qh, "ins.b", "0.0");
|
||||
err += check_key(qh, "ins.c", "0.0");
|
||||
|
||||
err += check_key(qh, "gen.a", "0.0");
|
||||
err += check_key(qh, "gen.b", "0.0");
|
||||
err += check_key(qh, "gen.c", "0.0");
|
||||
|
||||
err += check_key(qh, "obs.a", "0.0");
|
||||
err += check_key(qh, "obs.b", "0.0");
|
||||
err += check_key(qh, "obs.c", "0.0");
|
||||
|
||||
err += check_key(qh, "tpl.a", "0.0");
|
||||
err += check_key(qh, "tpl.b", "0.0");
|
||||
err += check_key(qh, "tpl.c", "0.0");
|
||||
|
||||
err += check_key(qh, "tel.a", "0.0");
|
||||
err += check_key(qh, "tel.b", "0.0");
|
||||
err += check_key(qh, "tel.c", "0.0");
|
||||
|
||||
err += check_key(qh, "log.a", "0.0");
|
||||
err += check_key(qh, "log.b", "0.0");
|
||||
err += check_key(qh, "log.c", "0.0");
|
||||
|
||||
err += check_key(qh, "null.a", "0.0");
|
||||
err += check_key(qh, "null.b", "0.0");
|
||||
err += check_key(qh, "null.c", "0.0");
|
||||
|
||||
say("removing keys");
|
||||
|
||||
qfits_header_del(qh, "PRO.A");
|
||||
qfits_header_del(qh, "pro.b");
|
||||
qfits_header_del(qh, "HIERARCH ESO PRO C");
|
||||
|
||||
if (qfits_header_getstr(qh, "HIERARCH ESO PRO A")!=NULL)
|
||||
err ++ ;
|
||||
if (qfits_header_getstr(qh, "PRO.B")!=NULL)
|
||||
err ++ ;
|
||||
if (qfits_header_getstr(qh, "pro.c")!=NULL)
|
||||
err ++ ;
|
||||
|
||||
say("modifying keys");
|
||||
|
||||
qfits_header_destroy(qh);
|
||||
return err ;
|
||||
}
|
||||
|
||||
int test_qfitsheader_browse(void)
|
||||
{
|
||||
qfits_header * qh ;
|
||||
char key[80], val[80], com[80] ;
|
||||
int i ;
|
||||
int err ;
|
||||
|
||||
say("-----> Header browsing test");
|
||||
/* Read header from source */
|
||||
say("reading header from file");
|
||||
qh = qfits_header_read(QFITSTESTFILENAME);
|
||||
if (qh==NULL) {
|
||||
fail("cannot read test file");
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
err=0 ;
|
||||
for (i=0 ; i<qh->n ; i++) {
|
||||
if (qfits_header_getitem(qh, i, key, val, com, NULL)!=0) {
|
||||
fail("cannot read header item");
|
||||
err++ ;
|
||||
}
|
||||
}
|
||||
qfits_header_destroy(qh);
|
||||
return err ;
|
||||
}
|
||||
|
||||
|
||||
int test_qfitspix_dump(void)
|
||||
{
|
||||
qfitsdumper qd ;
|
||||
|
||||
FILE * testfile ;
|
||||
byte testbuf[96] ;
|
||||
int i ;
|
||||
int err ;
|
||||
|
||||
/* Test various dumps to check pixel conversion works fine */
|
||||
say("-----> Pixel dumping tests: float pix");
|
||||
qd.filename = BINDUMPNAME;
|
||||
qd.npix = 12 ;
|
||||
|
||||
/* Test float dump */
|
||||
qd.ptype = PTYPE_FLOAT ;
|
||||
qd.fbuf = float_array_orig ;
|
||||
qd.out_ptype= -32 ;
|
||||
|
||||
say("dumping dat file");
|
||||
remove(BINDUMPNAME);
|
||||
if (qfits_pixdump(&qd)!=0) {
|
||||
fail("cannot save test buffer");
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
say("opening dat file");
|
||||
if ((testfile=fopen(BINDUMPNAME, "r"))==NULL) {
|
||||
fail("cannot open test file");
|
||||
return 1 ;
|
||||
}
|
||||
say("reading dat file");
|
||||
fread(testbuf, 4, 12, testfile);
|
||||
fclose(testfile);
|
||||
remove(BINDUMPNAME);
|
||||
|
||||
/* Compare arrays */
|
||||
say("comparing arrays");
|
||||
err=0 ;
|
||||
for (i=0 ; i<48 ; i++) {
|
||||
if (testbuf[i]!=float_array_byte[i]) {
|
||||
printf("failed: expected %02x got %02x\n",
|
||||
float_array_byte[i],
|
||||
testbuf[i]);
|
||||
err++ ;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test int dump */
|
||||
say("-----> Pixel dumping tests: int pix");
|
||||
qd.ptype = PTYPE_INT ;
|
||||
qd.ibuf = int_array_orig ;
|
||||
qd.out_ptype = 32 ;
|
||||
|
||||
say("dumping dat file");
|
||||
if (qfits_pixdump(&qd)!=0) {
|
||||
fail("cannot save test buffer");
|
||||
return 1 ;
|
||||
}
|
||||
say("opening dat file");
|
||||
if ((testfile=fopen(BINDUMPNAME, "r"))==NULL) {
|
||||
fail("cannot open test file");
|
||||
return 1 ;
|
||||
}
|
||||
say("reading dat file");
|
||||
fread(testbuf, 4, 12, testfile);
|
||||
fclose(testfile);
|
||||
remove(BINDUMPNAME);
|
||||
|
||||
/* Compare arrays */
|
||||
say("comparing arrays");
|
||||
err=0 ;
|
||||
for (i=0 ; i<48 ; i++) {
|
||||
if (testbuf[i]!=int_array_byte[i]) {
|
||||
printf("failed: expected %02x got %02x\n",
|
||||
int_array_byte[i],
|
||||
testbuf[i]);
|
||||
err++ ;
|
||||
}
|
||||
}
|
||||
remove(BINDUMPNAME);
|
||||
|
||||
/* Test double dump */
|
||||
say("-----> Pixel dumping tests: double pix");
|
||||
qd.ptype = PTYPE_DOUBLE ;
|
||||
qd.dbuf = double_array_orig ;
|
||||
qd.out_ptype = -64 ;
|
||||
|
||||
say("dumping dat file");
|
||||
if (qfits_pixdump(&qd)!=0) {
|
||||
fail("cannot save test buffer");
|
||||
return 1 ;
|
||||
}
|
||||
say("opening dat file");
|
||||
if ((testfile=fopen(BINDUMPNAME, "r"))==NULL) {
|
||||
fail("cannot open test file");
|
||||
return 1 ;
|
||||
}
|
||||
say("reading dat file");
|
||||
fread(testbuf, 8, 12, testfile);
|
||||
fclose(testfile);
|
||||
remove(BINDUMPNAME);
|
||||
|
||||
/* Compare arrays */
|
||||
say("comparing arrays");
|
||||
err=0 ;
|
||||
for (i=0 ; i<96 ; i++) {
|
||||
if (testbuf[i]!=double_array_byte[i]) {
|
||||
printf("failed: expected %02x got %02x\n",
|
||||
double_array_byte[i],
|
||||
testbuf[i]);
|
||||
err++ ;
|
||||
}
|
||||
}
|
||||
remove(BINDUMPNAME);
|
||||
|
||||
|
||||
return err ; ;
|
||||
}
|
||||
|
||||
int test_qfitsdata_dump(void)
|
||||
{
|
||||
qfitsdumper qd ;
|
||||
int i ;
|
||||
|
||||
say("-----> Data dumping test");
|
||||
/* Allocate data segment and save it to FITS file */
|
||||
qd.fbuf = malloc(11 * 10 * sizeof(float));
|
||||
for (i=0 ; i<(11*10) ; i++) {
|
||||
qd.fbuf[i]=i*0.2 ;
|
||||
}
|
||||
|
||||
qd.filename = QFITSTESTFILENAME ;
|
||||
qd.npix = 11 * 10 ;
|
||||
qd.ptype = PTYPE_FLOAT ;
|
||||
qd.out_ptype = -32 ;
|
||||
|
||||
if (qfits_pixdump(&qd)!=0) {
|
||||
fail("cannot save data to test file");
|
||||
free(qd.fbuf);
|
||||
return 1 ;
|
||||
}
|
||||
free(qd.fbuf);
|
||||
|
||||
/* Zero-pad the output file */
|
||||
qfits_zeropad(QFITSTESTFILENAME);
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
int test_qfitsdata_load(void)
|
||||
{
|
||||
qfitsloader ql ;
|
||||
int i ;
|
||||
int err ;
|
||||
float diff ;
|
||||
|
||||
err=0 ;
|
||||
say("-----> Data loading test");
|
||||
ql.filename = QFITSTESTFILENAME ;
|
||||
ql.xtnum = 0 ;
|
||||
ql.pnum = 0 ;
|
||||
ql.ptype = PTYPE_FLOAT ;
|
||||
|
||||
say("initializing loader");
|
||||
if (qfitsloader_init(&ql)!=0) {
|
||||
fail("cannot initialize loader on test file");
|
||||
return 1 ;
|
||||
}
|
||||
if (ql.lx != 11) {
|
||||
fail("wrong size in X");
|
||||
err++ ;
|
||||
}
|
||||
if (ql.ly != 10) {
|
||||
fail("wrong size in Y");
|
||||
err++ ;
|
||||
}
|
||||
|
||||
say("loading pixel buffer");
|
||||
if (qfits_loadpix(&ql)!=0) {
|
||||
fail("cannot load data from test file");
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
for (i=0 ; i<(11*10) ; i++) {
|
||||
diff = ql.fbuf[i] - (float)i * 0.2 ;
|
||||
if (diff>1e-4) {
|
||||
fail("diff in pix value");
|
||||
err++ ;
|
||||
}
|
||||
}
|
||||
free(ql.fbuf);
|
||||
return err ;
|
||||
|
||||
}
|
||||
|
||||
int test_qfits_extdump(void)
|
||||
{
|
||||
qfits_header * qh ;
|
||||
qfitsdumper qd ;
|
||||
FILE * out ;
|
||||
char * sig ;
|
||||
|
||||
say("-----> File with multiple extensions");
|
||||
/* Create minimal FITS header for main */
|
||||
say("creating default header");
|
||||
qh = qfits_header_default() ;
|
||||
if (qh==NULL) {
|
||||
fail("cannot create default header");
|
||||
return 1 ;
|
||||
}
|
||||
qfits_header_add(qh, "BITPIX", "8", "no data in main section", NULL);
|
||||
qfits_header_add(qh, "NAXIS", "0", "no data in main section", NULL);
|
||||
qfits_header_add(qh, "EXTEND", "T", "Extensions are present", NULL);
|
||||
|
||||
say("dumping header to test file");
|
||||
out = fopen(QFITSTESTFILENAME, "w");
|
||||
if (out==NULL) {
|
||||
fail("cannot create test file");
|
||||
qfits_header_destroy(qh);
|
||||
return 1 ;
|
||||
}
|
||||
qfits_header_dump(qh, out);
|
||||
fclose(out);
|
||||
qfits_header_destroy(qh);
|
||||
|
||||
say("creating first extension with float pixels");
|
||||
qh = qfits_header_new();
|
||||
if (qh==NULL) {
|
||||
fail("cannot create extension header 1");
|
||||
return 1 ;
|
||||
}
|
||||
qfits_header_append(qh, "XTENSION", "T", "Ext 1", NULL);
|
||||
qfits_header_append(qh, "BITPIX", "-32", "bpp", NULL);
|
||||
qfits_header_append(qh, "NAXIS", "2", "axes", NULL);
|
||||
qfits_header_append(qh, "NAXIS1", "6", "size in x", NULL);
|
||||
qfits_header_append(qh, "NAXIS2", "2", "size in y", NULL);
|
||||
qfits_header_append(qh, "END", NULL, NULL, NULL);
|
||||
|
||||
say("dumping ext header 1 to test file");
|
||||
out = fopen(QFITSTESTFILENAME, "a");
|
||||
if (out==NULL) {
|
||||
fail("cannot append to test file");
|
||||
qfits_header_destroy(qh);
|
||||
return 1 ;
|
||||
}
|
||||
qfits_header_dump(qh, out);
|
||||
fclose(out);
|
||||
qfits_header_destroy(qh);
|
||||
|
||||
say("dumping float array");
|
||||
|
||||
qd.filename = QFITSTESTFILENAME ;
|
||||
qd.npix = 12 ;
|
||||
qd.ptype = PTYPE_FLOAT ;
|
||||
qd.out_ptype = -32 ;
|
||||
qd.fbuf = float_array_orig ;
|
||||
|
||||
if (qfits_pixdump(&qd)!=0) {
|
||||
fail("cannot save data to test file");
|
||||
free(qd.fbuf);
|
||||
return 1 ;
|
||||
}
|
||||
/* Zero-pad the output file */
|
||||
qfits_zeropad(QFITSTESTFILENAME);
|
||||
|
||||
say("creating second extension with int pixels");
|
||||
qh = qfits_header_new();
|
||||
if (qh==NULL) {
|
||||
fail("cannot create extension header 1");
|
||||
return 1 ;
|
||||
}
|
||||
qfits_header_append(qh, "XTENSION", "T", "Ext 1", NULL);
|
||||
qfits_header_append(qh, "BITPIX", "32", "bpp", NULL);
|
||||
qfits_header_append(qh, "NAXIS", "2", "axes", NULL);
|
||||
qfits_header_append(qh, "NAXIS1", "6", "size in x", NULL);
|
||||
qfits_header_append(qh, "NAXIS2", "2", "size in y", NULL);
|
||||
qfits_header_append(qh, "END", NULL, NULL, NULL);
|
||||
|
||||
say("dumping ext header 2 to test file");
|
||||
out = fopen(QFITSTESTFILENAME, "a");
|
||||
if (out==NULL) {
|
||||
fail("cannot append to test file");
|
||||
qfits_header_destroy(qh);
|
||||
return 1 ;
|
||||
}
|
||||
qfits_header_dump(qh, out);
|
||||
fclose(out);
|
||||
qfits_header_destroy(qh);
|
||||
|
||||
say("dumping int array");
|
||||
|
||||
qd.filename = QFITSTESTFILENAME ;
|
||||
qd.npix = 12 ;
|
||||
qd.ptype = PTYPE_INT ;
|
||||
qd.out_ptype = 32 ;
|
||||
qd.ibuf = int_array_orig ;
|
||||
|
||||
if (qfits_pixdump(&qd)!=0) {
|
||||
fail("cannot save data to test file");
|
||||
free(qd.fbuf);
|
||||
return 1 ;
|
||||
}
|
||||
/* Zero-pad the output file */
|
||||
qfits_zeropad(QFITSTESTFILENAME);
|
||||
|
||||
say("creating third extension with double pixels");
|
||||
qh = qfits_header_new();
|
||||
if (qh==NULL) {
|
||||
fail("cannot create extension header 3");
|
||||
return 1 ;
|
||||
}
|
||||
qfits_header_append(qh, "XTENSION", "T", "Ext 1", NULL);
|
||||
qfits_header_append(qh, "BITPIX", "-64", "bpp", NULL);
|
||||
qfits_header_append(qh, "NAXIS", "2", "axes", NULL);
|
||||
qfits_header_append(qh, "NAXIS1", "6", "size in x", NULL);
|
||||
qfits_header_append(qh, "NAXIS2", "2", "size in y", NULL);
|
||||
qfits_header_append(qh, "END", NULL, NULL, NULL);
|
||||
|
||||
say("dumping ext header 3 to test file");
|
||||
out = fopen(QFITSTESTFILENAME, "a");
|
||||
if (out==NULL) {
|
||||
fail("cannot append to test file");
|
||||
qfits_header_destroy(qh);
|
||||
return 1 ;
|
||||
}
|
||||
qfits_header_dump(qh, out);
|
||||
fclose(out);
|
||||
qfits_header_destroy(qh);
|
||||
|
||||
say("dumping double array");
|
||||
|
||||
qd.filename = QFITSTESTFILENAME ;
|
||||
qd.npix = 12 ;
|
||||
qd.ptype = PTYPE_DOUBLE ;
|
||||
qd.out_ptype = -64 ;
|
||||
qd.dbuf = double_array_orig ;
|
||||
|
||||
if (qfits_pixdump(&qd)!=0) {
|
||||
fail("cannot save data to test file");
|
||||
free(qd.fbuf);
|
||||
return 1 ;
|
||||
}
|
||||
/* Zero-pad the output file */
|
||||
qfits_zeropad(QFITSTESTFILENAME);
|
||||
|
||||
/* Get MD5 for the test file */
|
||||
sig = qfits_datamd5(QFITSTESTFILENAME);
|
||||
if (strcmp(sig, REFSIG)) {
|
||||
fail("test file signature does not match");
|
||||
return 1 ;
|
||||
}
|
||||
say("file DATAMD5 signature is Ok");
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
int err ;
|
||||
|
||||
err=0 ;
|
||||
|
||||
/* Header tests */
|
||||
err += test_qfitsheader_create();
|
||||
err += test_qfitsheader_read();
|
||||
err += test_qfitsheader_browse();
|
||||
|
||||
/* Data tests */
|
||||
err += test_qfitsdata_dump();
|
||||
err += test_qfitsdata_load();
|
||||
err += test_qfitspix_dump() ;
|
||||
|
||||
/* Extension tests */
|
||||
err += test_qfits_extdump();
|
||||
|
||||
remove(QFITSTESTFILENAME);
|
||||
|
||||
fprintf(stderr, "total error(s): %d\n", err);
|
||||
return err ;
|
||||
}
|
Loading…
Reference in New Issue